• 文档
  • 知识库
  • 教程
  • OpenHarmony

【免费下载链接】CangjieCorpus

本仓库为仓颉编程语言语料库,聚焦 仓颉编程语言 核心知识体系,整合官方开发指南、API 文档、典型代码示例及语法规范等多维度资源,经结构化处理与专业标注,构建为支持 RAG(检索增强生成)技术 的高质量知识基座,适配智能编码助手、学习辅助工具等应用开发需求。 欢迎开发者基于本语料库构建仓颉语言智能应用,推动鸿蒙开发生态智能化升级!

项目地址: https://gitcode.com/Cangjie/CangjieCorpus
点击查看 免费下载

仓颉编程语言是面向全场景应用开发的通用编程语言,兼顾开发效率与运行性能。本指南以 CangjieCorpus 语料库中"学习仓颉语言"主题导航为核心骨架,系统梳理仓颉从语法基础(标识符、程序结构、表达式、函数、数据类型)到进阶特性(枚举与模式匹配、泛型、类与接口、宏、反射注解、并发),再到工程实践(包管理、编译构建、条件编译)与跨语言互操作(C、ArkTS)的完整学习路径,并给出每一主题在仓库中的权威文档位置与可运行代码示例。读完本文,你将获得一张可直接照图索骥的仓颉语言学习地图,并能快速定位到对应源码与实战案例进行深入研读。

初识仓颉语言:语言定位与核心特性

在正式进入语法细节之前,先建立对仓颉语言的整体认知。根据初识仓颉语言的官方定义,仓颉是一门面向全场景应用开发的通用编程语言,其核心特性可归纳为:

  • 多后端支持:支持 CJNative(编译为原生二进制代码,直接运行于操作系统)与 CJVM(编译为字节码,基于虚拟机运行)两种后端。当前 SDK 提供 CJNative 后端,CJVM 后端 SDK 敬请期待。
  • 语法简明高效:提供插值字符串、主构造函数、Flow 表达式、match、重导出等语法,用较少编码表达复杂逻辑。
  • 多范式编程:融合函数式(高阶函数、代数数据类型、模式匹配、泛型)、面向对象(封装、接口、继承、子类型多态)与命令式(值类型、全局函数)编程范式。
  • 类型安全:静态强类型语言,通过编译时类型检查尽早识别错误,同时编译器提供强大的类型推断能力,减少类型标注工作。
  • 内存安全:支持自动内存管理,并在运行时进行数组下标越界检查、溢出检查等操作。
  • 高效并发:提供用户态轻量化线程(原生协程)以及简单易用的并发编程机制。
  • 兼容语言生态:支持与 C 等语言的互操作,采用声明式编程范式实现其他语言库的高效复用。
  • 领域易扩展:提供基于词法宏的元编程能力,支持编译时变换代码,配合尾随 lambda、属性、操作符重载等特性,有利于内嵌式领域专用语言(EDSL)的构建。
  • 助力 UI 开发:基于元编程和尾随 lambda 等特性,可搭建声明式 UI 开发框架。
  • 内置库功能丰富:涉及数据结构、常用算法、数学计算、正则匹配、系统交互、文件操作、网络通信、数据库访问、日志打印、解压缩、编解码、加解密和序列化等。

动手体验的最快方式是编写并运行第一个程序。在运行第一个仓颉程序中,新建 hello.cj 文件:

// hello.cj
main() {
    println("你好,仓颉")
}

然后执行编译命令(Linux/macOS 平台;Windows 平台将输出名改为 hello.exe 即可):

cjc hello.cj -o hello

运行生成的可执行文件即可看到输出 你好,仓颉。注意仓颉支持 // 单行注释与 /* */ 多行注释,与 C/C++ 语法相同。

基本概念:标识符、程序结构与表达式

标识符

标识符用于为程序元素命名,分为普通标识符和原始标识符两类。仓颉采用 Unicode 标准 15.0.0,依据 XID_Start 与 XID_Continue 属性判定合法字符,因此中文可以直接用作标识符。

  • 普通标识符:由 XID_Start 字符开头后接任意长度 XID_Continue 字符;或由 _ 开头后接至少一个 XID_Continue 字符。合法示例:abc、_abc、a1_b2_c3、仓颉、__こんにちは。不合法示例:3abc(数字不能开头)、_(_ 后至少需要一个字符)、while(关键字)。
  • 原始标识符:在普通标识符或关键字首尾加反引号,用于将关键字当作标识符,如 `if`、`while`。

所有标识符被识别为 NFC(Normalization Form C)规范化后的形式,两个标识符若 NFC 后相等则视为相同。

程序结构

程序结构规定,仓颉源代码文件以 .cj 为扩展名。顶层作用域可以定义全局变量、全局函数和自定义类型(struct、class、enum、interface);编译为可执行文件时必须在顶层定义 main 作为程序入口。main 可以不写 func 修饰符,可带 Array<String> 参数,返回类型为整数类型或 Unit。

let a = 2023
func b() {}
struct C {}
class D {}
enum E { F | G }

main() {
    println(a)
}

变量方面,仓颉变量定义形式为 修饰符 变量名: 变量类型 = 初始值,关键修饰符包括:

  • 可变性修饰符:let(不可变,只能赋值一次即初始化)与 var(可变,可多次赋值),二者为必需修饰符。
  • const:编译期求值、运行时不可改变的常量,声明时必须初始化;const 变量初始化后该实例所有成员均为 const(深度 const)。
  • 可见性修饰符:private、public 等;静态性修饰符:static。

仓颉变量分为值类型变量(struct 及基础类型等,赋值产生拷贝)和引用类型变量(class、Array 等,赋值建立引用关系,多个变量可共享同一数据对象)。例如对 struct Copy 赋值 c2 = c1 后修改 c2.data 不影响 c1;对 class Share 赋值 s2 = s1 后修改 s2.data 会连带影响 s1。这一点在阅读数组类型时同样重要——Array 虽是 struct 类型,但其内部持有元素引用,所有引用共享元素数据。

作用域由大括号 {} 构造,嵌套作用域遵循"内层可访问外层绑定、内层定义可遮盖外层同名定义"的规则;顶层作用域级别最低。注意仓颉不允许使用单独的大括号,大括号必须依附于 if、match、函数体、类体等语法结构。

表达式

表达式定义"凡可求值的语言元素都是表达式",因此除算术表达式外,条件表达式、循环表达式、try 表达式等均可求值并作为值使用。

  • if 表达式:if (条件) {分支 1} else {分支 2},条件是布尔类型表达式或 let pattern 语法糖。仓颉是强类型语言,if 条件不能使用整数或浮点数(与 C 语言以非零为真的规则不同)。含 else 分支的 if 表达式求值时,其类型为各分支的最小公共父类型;未求值时类型为 Unit。
  • let pattern:构成为 let pattern <- expression,可在 if 条件中通过逻辑与(&&)或逻辑或(||)组合,例如 if (let Some(b) <- a && let Some(f) <- d)。
  • while 与 do-while 表达式:均为布尔条件驱动循环,类型为 Unit。
  • for-in 表达式:遍历扩展了 Iterable<T> 接口的类型实例(内置区间和数组已实现)。迭代变量不可修改;可用通配符 _ 代替迭代变量以避免 unused variable 告警;支持 where 条件过滤,如 for (i in 0..8 where i % 2 == 1)。
  • break 与 continue 表达式:类型均为 Nothing,用于终止循环或跳过本轮。

关于"代码块"的求值规则:代码块的值与类型等于最后一个表达式的值与类型;空代码块类型为 Unit。

基础数据类型:整数、浮点、布尔、字符、字符串、元组、数组、区间与特殊类型

基础数据类型是仓颉语法的基石,各类型详解可参见 basic_data_type 目录:

  • 基本操作符:各类操作符及优先级总览,详细优先级表见附录操作符。
  • 整数类型:有符号(Int8/Int16/Int32/Int64/IntNative)与无符号(UInt8/UInt16/UInt32/UInt64/UIntNative)。N 位有符号整数范围 -2^(N-1) ~ 2^(N-1)-1,无符号范围 0 ~ 2^N-1。在 Int64 适合时首选 Int64(整数字面量在无上下文时默认推断为 Int64)。字面量支持 0b/0B(二进制)、0o/0O(八进制)、十进制、0x/0X(十六进制),可用 _ 作分隔符,并支持 i8/u8/i16/u16/i32/u32/i64/u64 后缀明确类型。还支持字符字节字面量(如 b'x' 为 UInt8 类型 120),以及算术、位、关系、自增自减、复合赋值等操作符。
  • 浮点类型:Float32 与 Float64,支持科学计数法等字面量形式。
  • 布尔类型:Bool 类型,取值 true/false,支持逻辑与(&&)、逻辑或(||)、逻辑非(!)等操作。
  • 字符类型:Rune 表示 Unicode 字符,字符字面量以 r 开头(如 r'甲'),详见字符类型字面量章节。
  • 字符串类型:String 类型由 Unicode 字符组合而成。字面量分三类:单行(单引号/双引号)、多行("""/''')、多行原始字符串(#""# 形式,转义规则不适用)。插值字符串用 ${} 包裹表达式,如 "There are ${count * count} ${fruit}",可用于避免字符串拼接。字符串支持关系比较、+ 拼接,以及 contains、split 等常见操作(完整 API 见 extra/String.md)。
  • 元组类型:将多个值组合为单一复合值,可用于 for-in 遍历时解构序列元素。
  • 数组类型:Array<T> 是单一元素类型的有序序列。支持字面量初始化([1, 2, 3])、构造函数初始化(Array<Int64>(3, repeat: 0)、Array<Int64>(3, {i => i + 1}))。通过下标访问(类型必须为 Int64,越界时编译器可查则报编译错误,否则运行时抛异常),支持 Range 切片(arr1[0..5]、arr1[..3]、arr1[2..])。Array 长度不可变、不提供增删元素成员函数,但可修改已有元素。此外仓颉还引入值类型数组 VArray<T, $N>,可减少堆上内存分配与 GC 压力,但传递/赋值时会产生拷贝开销,不建议在性能敏感场景使用较大长度 VArray;VArray 还用于仓颉与 C 数组的映射(见 cangjie-c.md)。
  • 区间类型:Range 支持 ..(含首不含尾)与 ..=(含首含尾)两种形式,可直接用于 for-in 遍历(如 for (i in 1..=100) 求 1 到 100 之和)。
  • Unit 类型:空类型,值为 (),类似其他语言的 void,用于表示无意义返回值。
  • Nothing 类型:所有类型的子类型,break/continue/return 等控制转移表达式的类型均为 Nothing。

函数:定义、调用、Lambda、闭包、重载与操作符重载

函数以关键字 func 开头,依次为函数名、参数列表、可选返回值类型(冒号分隔)、函数体。

定义函数

定义函数中,参数分为非命名参数(p: T)与命名参数(p!: T,调用时需给定参数名);只能为命名参数设置默认值(p!: T = e),且非命名参数必须定义在命名参数之前。函数参数均为不可变变量,函数体内不能赋值。返回值类型可显式声明也可由编译器根据函数体和 return 表达式推导;指定 Unit 时编译器会在所有可能返回处自动插入 return ()。return 表达式类型为 Nothing。函数体的类型为最后一项的类型(表达式为表达式类型,变量定义/函数声明/空体为 Unit)。

调用函数、函数类型与嵌套函数

  • 调用函数:区分非命名参数与命名参数的调用方式差异。
  • 函数类型:函数是头等公民,函数类型形如 (Int64) -> Int64,可作为变量类型、参数和返回值。
  • 嵌套函数:允许在函数体内定义局部函数。

Lambda 表达式与闭包

Lambda 表达式语法为 { p1: T1, ..., pn: Tn => expressions | declarations }。无论有无参数,=> 都不可省略(尾随 lambda 除外)。参数类型可缺省,由上下文推断(赋值给变量时按变量类型推断,作实参时按形参类型推断);不支持声明返回类型,从上下文或表达式体推导。Lambda 支持立即调用:let r1 = { a: Int64, b: Int64 => a + b }(1, 2),也可赋值给变量后调用。仓颉的函数调用语法糖中包括尾随 lambda,使得 f2 { println("World") } 可省略 =>。闭包在函数调用语法糖基础上进一步讲解捕获外部变量的行为。

函数重载与操作符重载

函数重载允许多个同名函数通过参数类型/数量区分;操作符重载允许为自定义类型定义操作符行为(操作符与操作符函数的对应关系见附录操作符函数)。

const 函数与常量求值

const 函数和常量求值讲解 const 函数在编译期完成求值的能力,与程序结构中 const 变量配合,可在编译期计算常量表达式。

结构类型(struct)

struct 是仓颉的值类型。三篇文档构成完整脉络:

注意 struct 是值类型,赋值/传参时产生拷贝,与 class(引用类型)行为不同;struct 之间不能继承。

枚举类型与模式匹配

枚举类型

枚举类型可理解为函数式语言中的代数数据类型(ADT)。以 enum 关键字定义,构造器(constructor)之间用 | 分隔:

enum RGBColor {
    | Red(UInt8) | Green(UInt8) | Blue(UInt8)
}
  • 支持同名构造器重载(参数个数不同);每个 enum 至少有一个有名字的构造器。
  • 支持 ... 无名字构造器形成 non-exhaustive enum,此时匹配需使用通配符 _ 或绑定模式。
  • 支持递归定义(如表达式树 Expr 的 Add(Expr, Expr))。
  • enum 只能定义在顶层作用域;enum 值通过 类型名.构造器 或直接使用构造器构造,名字冲突时必须加类型名。

Option 类型

Option 类型是预定义的泛型 enum:

enum Option<T> {
    | Some(T)
    | None
}

它包含 Some(有值)和 None(无值)两个构造器,用于表示"可能有值也可能没有值"的场景。Option<T> 有简写 ?T(?Int64 等价于 Option<Int64>)。当上下文明确需要 Option<T> 时可直接传 T 值(编译器用 Some 封装);无上下文时构造 None 需使用 None<T> 语法。

模式概述与 match 表达式

模式概述系统介绍常量模式、通配符模式、绑定模式、enum 模式等各类模式;Refutability 讨论模式的可反驳性(refutable/irrefutable)。

match 表达式支持含匹配值与不含匹配值两种形式。含匹配值形式以 case 模式 => 操作 组织分支,支持 pattern guard(where cond)和 | 连接多个模式:

let c = RGBColor.Green(-100)
let cs = match (c) {
    case Red(r) where r < 0 => "Red = 0"
    case Red(r) => "Red = ${r}"
    case Green(g) where g < 0 => "Green = 0"
    case Green(g) => "Green = ${g}"
    case Blue(b) where b < 0 => "Blue = 0"
    case Blue(b) => "Blue = ${b}"
}

match 要求穷尽性:所有 case 覆盖范围的并集必须包含待匹配值的所有可能取值,否则编译报错;常用最后一个 case _ 通配分支保证穷尽。无匹配值形式则在 case 后直接放 Bool 表达式。match 表达式的类型为各分支最小公共父类型;值未被使用时类型为 Unit。其他使用模式的地方(如变量定义处解构)见其他。

类和接口:面向对象编程

类是面向对象的核心。class 是引用类型,与 struct(值类型)行为不同,且支持继承。

  • 定义:class 定义体含成员变量(实例/静态)、静态初始化器(static init)、构造函数、成员函数、操作符函数。class 只能定义在顶层作用域。

  • 构造函数:普通构造函数以 init 开头;主构造函数名字与类名相同,其成员变量形参(let/var 前缀)同时具有定义成员变量和构造函数参数的功能,可大幅简化类定义:

    class Rectangle {
        public Rectangle(let width: Int64, let height: Int64) {}
    }
    

    创建实例时按"初始化有缺省值的变量 → 调用父类无参构造(如未显式调用)→ 执行构造体"的顺序执行。

  • 终结器:~init 在实例被 GC 回收时调用,用于释放系统资源,但有严格限制(无参数、类不可 open、触发时机不确定、执行线程不确定、依赖终结器的同步行为属于未定义行为等)。

  • 继承:非抽象类需用 open 修饰才可被继承,子类用 <: 指定父类;单继承,所有类的最终父类为 Object。子类对象可赋给父类变量,反之不行。覆盖父类成员函数用 override,重定义父类静态函数用 redef;覆盖基于运行时类型动态派发。

  • 访问修饰符:private(类内可见)、internal(当前包及子包可见,缺省值)、protected(当前模块及子类可见)、public(模块内外可见)。

  • This 类型:This 占位符代指当前类类型,作为实例成员函数返回类型时会被识别为子类类型,支持流畅的链式设计。

接口定义抽象行为契约,类可实现多个接口;属性讲解成员属性的定义与访问控制;子类型关系系统阐述子类型判定规则;类型转换覆盖数值类型间转换、as 转换与向下转型等规则。

泛型

泛型概述定义参数化类型的关键术语:类型形参(声明时未知的类型,如 List<T> 的 T)、类型变元(声明体中对形参的引用)、类型实参(使用处指定的具体类型,如 List<Int64> 的 Int64)、类型构造器。在仓颉中,function、class、interface、struct、enum 均可声明泛型:

class List<T> {
    var elem: Option<T> = None
    var tail: Option<List<T>> = None
}

泛型专题共 9 篇文档:泛型函数、泛型接口、泛型类、泛型结构体、泛型枚举、泛型类型的子类型关系、类型别名(type 关键字)、泛型约束(where T <: SomeType 形式)。泛型约束在 C 互操作中同样常见,如 where T <: CType。

扩展机制

扩展概述引入仓颉的扩展能力,允许为已有类型补充成员。三篇文档构成完整体系:

Collection 类型:ArrayList、HashSet、HashMap 与迭代

基础 Collection 类型概述给出四类常用容器的选型建议与特性对比:

类型名称元素可变增删元素元素唯一性有序序列
Array<T>YNNY
ArrayList<T>YYNY
HashSet<T>NYYN
HashMap<K, V>K: N, V: YYK: Y, V: NN
  • Array:不需要增删元素但需要修改元素的场景。
  • ArrayList:需要频繁增删查改元素。
  • HashSet:希望每个元素唯一。
  • HashMap:存储键值映射关系。
  • Iterable 和 Collections:迭代器接口与遍历机制,for-in 的底层依据。

标准库 collection 包的完整 API 与实战示例可进一步参阅 collection_package_overview 及其 samples(如 sample_arraylist_add、sample_hashmap_add_remove_clear 等)。

包:组织、导入与程序入口

随着项目规模扩大,需要将源代码按功能分组管理。包的概述明确两个关键概念:

  • 包是编译的最小单元,每个包可单独输出 AST 文件、静态库、动态库等产物;同一包内不允许同名顶层定义(函数重载除外),一个包可含多个源文件。
  • 模块是若干包的集合,是第三方开发者发布的最小单元;程序入口只能位于模块根目录,顶层最多一个 main。

包的声明讲解 package 声明语法;顶层声明的可见性规定包内/包间访问规则。

包的导入核心语法为 import fullPackageName.itemName,支持:

  • 批量导入:import fullPackageName.{item1, item2} 与通配导入 import packageName.*。
  • 重导出:import 可被 private(默认)、internal、protected、public 修饰,public/protected/internal import 可将导入成员重导出给其他包使用;包本身不可被重导出。
  • import as 重命名:解决不同包同名声明冲突,如 import p1.C as C1、import p1 as A;重命名后原名不可用。
  • 约束:禁止导入当前源文件所在包的声明,禁止包间循环依赖,只允许导入当前文件可见的顶层声明。
  • 隐式导入 core 包:String、Range 等类型可直接使用,是因为编译器自动隐式导入 core 包中所有 public 声明。

程序入口规定:可执行编译方式下编译器只在源文件根目录顶层查找 main;main 不可被访问修饰符修饰,可无参数或参数为 Array<String>,返回 Unit 或整数类型。无参数 main 示例:

main(): Int64 {
    return 0
}

带参数示例:

main(args: Array<String>): Unit {
    for (arg in args) {
        println(arg)
    }
}

编译后执行 ./main Hello, World 将逐行打印 Hello, 与 World。若 main 返回 String、参数非 Array<String> 或存在多个 main,均编译报错。

异常处理

定义异常区分两类异常基类:

  • Error:运行时系统内部错误与资源耗尽错误,应用程序不应抛出,出现时尽量安全终止程序;不可继承。
  • Exception:程序运行时逻辑错误或 IO 错误导致的异常(如数组越界、打开不存在的文件),需在程序中捕获处理;可通过继承自定义。

Exception 的主要成员包括构造函数 init()/init(message: String)、属性 message、函数 toString()、getClassName()、printStackTrace()。

throw 和处理异常以 throw 抛出异常(throw 后表达式必须是 Exception 子类型,Error 不可手动 throw),以 try 表达式捕获处理:

  • 普通 try 表达式:由 try 块、catch 块(零个或多个)、finally 块(无 catch 时必须有 finally)组成。catchPattern 通过模式匹配捕获异常,支持类型模式(e: ExceptionClass,可用 | 连接多个异常类,此时被捕获异常类型为各类型最小公共父类)和通配符模式(_,等价于 e: Exception)。
  • try-with-resources 表达式:用于自动释放非内存资源,try (r = ResourceType(...)) 形式,资源类型必须实现 Resource 接口(isClosed(): Bool 与 close(): Unit)。catch/finally 可选,表达式类型为 Unit。

异常处理专题还包含常见运行时异常(如 ArithmeticException、NegativeArraySizeException、OverflowException、IllegalArgumentException 等)与使用 Option(以 Option 类型替代异常处理的可空值场景)。

并发编程

并发概述介绍仓颉采用抢占式线程模型,区分语言线程与 native 线程:

  • 仓颉线程:用户态轻量级线程,采用 M:N 线程模型(M 个语言线程在 N 个 native 线程上调度),支持抢占且比操作系统线程更轻量。
  • native 线程:语言线程的实现载体(一般为操作系统线程)。

大多数场景下开发者只需面向仓颉线程编程,但跨语言编程时需谨慎调用可能阻塞的 foreign 函数(如 IO 系统调用),否则会阻塞 native 线程、降低吞吐量。

创建线程使用 spawn 关键字并传递无形参 lambda:

main(): Int64 {
    spawn { =>
        println("New thread before sleeping")
        sleep(100 * Duration.millisecond)
        println("New thread after sleeping")
    }
    println("Main thread")
    return 0
}

新线程会在主线程结束时一起停止。线程睡眠指定时长 sleep 详解 sleep() 的 Duration 用法。访问线程介绍线程句柄与状态访问;终止线程讲解线程终止机制;同步机制覆盖互斥锁等并发同步原语,标准库 sync 包 API 见 sync_package_overview。

基础 I/O 与网络编程

  • I/O 流概述:仓颉 I/O 流体系总览,基于 std.io 包。
  • I/O 节点流:数据源端流(如文件、字节缓冲)。
  • I/O 处理流:对节点流进行加工的处理流(缓冲、链式、多路输出等)。

相关标准库实战示例见 io_samples(如 buffered_input_stream、string_reader)与 console_package_overview。

网络编程专题四篇:网络编程概述、Socket 编程(TCP/UDP/UNIX,见 net_samples)、HTTP 编程、WebSocket 编程。

宏:基于词法宏的元编程

宏的简介将宏定义为"输入和输出都是程序本身"的特殊函数,调用时使用 @ 加宏名称。一个经典例子是打印表达式值的 @dprint 宏:

macro package define

import std.ast.*

public macro dprint(input: Tokens): Tokens {
    let inputStr = input.toString()
    let result = quote(
        print($(inputStr) + " = ")
        println($(input)))
    return result
}

关键要点:

  • 宏必须声明在独立包中,使用 macro package 声明;实现宏所需类型(Tokens、语法节点)位于标准库 ast 包,故需 import std.ast.*。
  • quote 表达式用于构造 Tokens,插值 $(...) 可将表达式/值转换为 Tokens 插入。
  • 编译命令为 cjc define/*.cj --compile-macro 后 cjc main.cj -o main。

宏专题完整链路:Tokens 相关类型和 quote 表达式、语法节点、宏的实现、编译、报错与调试、宏包定义和导入、内置编译标记、实用案例。注意原导航文档中"语法节点"与"实用案例"的目标文件名在仓库中实际为 sytax_node.md 与 pratical_case.md。

反射和注解

跨语言互操作:仓颉-C 与仓颉-ArkTS

仓颉与 C 互操作

仓颉-C 互操作是兼容既有生态的关键能力,支持双向调用。核心机制包括:

  • foreign 关键字:声明 C 侧函数,只能有声明不能有实现;参数和返回类型须符合 C/仓颉类型映射;调用需在 unsafe 块中。@C 修饰 foreign 时可省略。
  • CFunc:可被 C 调用的函数(@C 修饰的 foreign 函数、@C 修饰的仓颉函数、CFunc 类型的 lambda——不能捕获变量),对应 C 函数指针。
  • inout 参数:按引用传值,类型为 CPointer<T>;仅可用于 CFunc 调用处,不能来源于 class 实例成员变量。
  • unsafe:用于标识跨 C 调用的不安全行为,可修饰函数、表达式或作用域。
  • 调用约定 @CallingConv:支持 CDECL(默认)与 STDCALL。
  • 类型映射:基础类型(Int64↔int64_t 等,IntNative↔ssize_t)、结构体(@C 修饰的 struct)、指针(CPointer<T>)、数组(VArray<T, $N>,不支持 C 柔性数组映射)、字符串(CString,通过 LibC.mallocCString 创建、用完需释放)。
  • sizeOf/alignOf:获取 C 互操作类型的内存占用与对齐字节数。
  • CType 接口:所有 C 互操作支持类型的父类型,用于泛型约束。
  • 编译选项:--library-path/-L 指定库搜索目录,--library/-l 指定链接库。完整示例(C 侧 drawPicture 与仓颉侧 Point/Cube 结构体交互)以 cjc -L . -l draw ./main.cj 编译,运行需 LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main。

仓颉与 ArkTS 互操作(OpenHarmony 场景)

在 OpenHarmony 应用中,仓颉与 ArkTS 的混合开发是核心实践场景,相关文档位于 ohos/zh-cn/application-dev/learn-cj/FFI,入门路径为:

  • 构建第一个仓颉与 ArkTS 混合应用:在 DevEco Studio 中选择 [Cangjie] Hybrid Ability 模板创建混合工程,理解 entry/src/main/cangjie(仓颉源码)与 entry/src/main/ets(ArkTS 源码)的目录分工。仓颉页面以组件形式嵌入 ArkTS 页面(通过 CJHybridComponent 接口,需指定 library 与 component 名称),页面路由通过 router 实现,且仓颉与 ArkTS 的 router 不互通,需通过声明式互操作宏(@Interop[ArkTS])将 ArkTS 侧路由函数注册给仓颉调用。
  • 在已有 ArkTS 工程中增量使用仓颉:存量工程增量接入。
  • 在仓颉代码里导入 ArkTS 模块:仓颉侧导入 ArkTS 模块。

进阶专题包括:概述、场景、互操作用法(声明式互操作宏、互操作库、ArkTS 侧使用互操作代码、仓颉侧调用互操作代码)、互操作使用案例(仓颉访问 ArkTS 数据、ArkTS 访问仓颉数据、仓颉多线程中使用互操作)、辅助库与开发规范。

编译和构建:cjc、cjpm 与条件编译

cjc 编译器

cjc 使用介绍编译命令基本用法,命令形式为 cjc [option] file...。cjc 会自动完成前端、后端编译与链接;cjc-frontend 仅进行前端编译至 LLVM IR,编译流程在前端结束中止,除编译器开发者外应优先使用 cjc。对 hello.cj 直接执行 cjc hello.cj 会在工作目录生成可执行文件 main(默认行为);可通过编译选项控制整包编译或指定输出文件名。全部编译选项详见 cjc 编译选项。

cjpm 包管理

CJPM(Cangjie Package Manager)是仓颉官方包管理工具,核心子命令包括:

子命令说明
init初始化新仓颉模块(创建 cjpm.toml 与 src/main.cj)
check检查依赖
update更新 cjpm.lock
tree显示源码依赖树
build编译当前模块(先检查依赖,再调用 cjc;-V 打印全部编译过程命令)
run编译并运行可执行产物
test / bench本地包或模块单测 / 基准测试
clean清理 target 目录
install / uninstall安装 / 卸载仓颉二进制

cjpm.toml 配置文件的关键字段:

  • [package]:cjc-version(所需 cjc 最低版本,必需)、name(模块名及 root 包名,必需)、version(必需)、output-type(输出类型,如 executable,必需)、compile-option/override-compile-option/link-option(额外编译/链接选项)、src-dir/target-dir、package-configuration。
  • [workspace]:members(成员模块列表,必需)、build-members/test-members 及全局编译选项,与 [package] 不能同时存在。
  • [dependencies]/[test-dependencies]/[script-dependencies]/[replace]:以 git 或 path 形式声明源码依赖。
  • [ffi.c]:导入 C 语言库依赖。
  • [profile]:build/test/bench 命令剖面配置。
  • [target.xxx]:按后端和平台隔离的编译选项与依赖(含 bin-dependencies 二进制库依赖,支持目录与单文件两种形式)。

条件编译

条件编译使用内置编译标记 @When,编译条件用 [] 括起,可作用于导入节点和除 package 外的声明节点。基本用法:

@When[os == "Linux"]
class mc{}

main(): Int64 {
    var a = mc()
    return 0
}

内置编译条件变量包括:

  • os:目标平台操作系统,支持 Windows、Linux、macOS,可用 ==/!=。
  • backend:后端类型,支持 cjnative、cjvm。
  • arch:处理器架构,支持 x86_64、aarch64。
  • cjc_version:编译器版本,支持 ==/!=/>/</>=/<=,按补位(补齐 2 位)比较。
  • debug:是否开启 -g 调试选项,仅支持 !。
  • test:是否启用 --test 单测选项,仅支持 !。

自定义条件变量需通过 --cfg 编译选项(键值对形式,如 cjc --cfg "feature = lion, platform = dsp" source.cj)或 cfg.toml 配置文件(--cfg "./cfg" 指定搜索路径,文件内每行一个 键 = "值")定义。支持逻辑运算符组合多条件与括号明确优先级,例如:

@When[(test || feature == "lion") && !debug]
func fee() {
    println("feature lion")
}

注意仓颉不支持条件编译嵌套;宏展开生成的代码中含有 @When[...] 会编译报错。

附录:编译选项、关键字、操作符与 TokenKind

学习导航的附录部分提供语法速查资料:

  • cjc 编译选项:完整编译选项参考,如 -o(输出名)、-p/--package(指定包目录)、-g(调试模式)、--cfg(条件编译配置)、--test(单测)、-L/-l(链接库)、--compile-macro(宏编译)、--output-type(输出类型)等。
  • 关键字:仓颉全部关键字清单,也是判断原始标识符用法的依据。
  • 操作符:全部操作符及其优先级表。
  • 操作符函数:操作符与可重载函数的对应关系。
  • TokenKind 类型:词法 Token 类型枚举,宏开发与语法分析的基础。

学习路径总结

综合以上内容,仓颉语言的学习可按如下路线推进:

  1. 入门:阅读初识仓颉语言与运行第一个仓颉程序,建立语言整体认知并跑通编译运行链路。
  2. 基础语法:依次掌握基本概念(标识符、程序结构、表达式、函数)与基础数据类型。
  3. 进阶语言特性:函数专题 → 结构类型 → 枚举与模式匹配 → 类与接口 → 泛型 → 扩展,逐步构建多范式编程能力。
  4. 工程能力:Collection 容器选型 → 包组织与导入 → 异常处理 → 并发编程 → I/O 与网络。
  5. 元编程与互操作:宏、反射注解、仓颉-C 互操作;在 OpenHarmony 场景下进阶仓颉-ArkTS 混合开发。
  6. 编译构建:掌握 cjc/cjpm/条件编译,并随时查阅附录速查资料。

每一专题在 CangjieCorpus 仓库中均有对应文档与可验证代码示例(含编译错误示例以强化边界认知),标准库 API 与 samples 见 libs/std 各包目录,OpenHarmony 应用开发体系见 ohos/zh-cn/application-dev,可结合本路线图按需深入研读。

  • 文档
  • 知识库
  • 教程
  • OpenHarmony

【免费下载链接】CangjieCorpus

本仓库为仓颉编程语言语料库,聚焦 仓颉编程语言 核心知识体系,整合官方开发指南、API 文档、典型代码示例及语法规范等多维度资源,经结构化处理与专业标注,构建为支持 RAG(检索增强生成)技术 的高质量知识基座,适配智能编码助手、学习辅助工具等应用开发需求。 欢迎开发者基于本语料库构建仓颉语言智能应用,推动鸿蒙开发生态智能化升级!

项目地址: https://gitcode.com/Cangjie/CangjieCorpus
点击查看 免费下载
Logo

邀请您加入社区

更多推荐