Cangjie-ArkTS Interoperability Library
Note:
It is recommended to use the Declarative Interoperability Macro approach for ArkTS to call Cangjie modules. Only use the "Cangjie-ArkTS Interoperability Library" method when the macro approach cannot meet developer requirements.
To develop a Cangjie interoperability module:
-
Create a Cangjie module in an ArkTS project. For details, refer to Adding a Cangjie Module to an ArkTS Project.
-
Construct code in the generated Cangjie file as shown in the following example:
// Define the package name, which must match the package name in cjpm.toml package ohos_app_cangjie_entry // Import the interoperability library import ohos.ark_interop.* // Define the interoperability function. The parameter type must be (JSContext,JSCallInfo), and the return type must be JSValue func addNumber(context: JSContext, callInfo: JSCallInfo): JSValue { // Get arguments from JSCallInfo let arg0: JSValue = callInfo[0] let arg1: JSValue = callInfo[1] // Convert JSValue to Cangjie types let a: Float64 = arg0.toNumber() let b: Float64 = arg1.toNumber() // Actual Cangjie function behavior let value = a + b // Convert the result to JSValue let result: JSValue = context.number(value).toJSValue() // Return JSValue return result } // Must register the function to JSModule let EXPORT_MODULE = JSModule.registerModule { runtime, exports => exports["addNumber"] = runtime.function(addNumber).toJSValue() } -
In the cangjie->types->libohos_app_cangjie_entry->Index.d.ts file, provide the interface declaration for interoperability:
// entry/src/main/cangjie/types/libohos_app_cangjie_entry/Index.d.ts export declare function addNumber(a: number, b: number): number; -
On the ArkTS calling side, the code is as follows:
// Import the Cangjie dynamic library. The library name should match the Cangjie package name, which must be consistent with the package name where the interoperability interface resides. import { addNumber } from "libohos_app_cangjie_entry.so"; // Call the Cangjie interface let result = addNumber(1, 2); console.log(`1 + 2 = ${result}`);
In the above process, the exported function defined on the Cangjie side uses the most basic Cangjie types through the interoperability library. For other types, refer to the chapters Using ArkTS Data in Cangjie and Operating Cangjie Objects in ArkTS.
Warning:
Within the same Cangjie module (the same package and its sub-packages), the following rules must be followed to avoid symbol conflicts:
Functions, interfaces, and classes registered to JSModule using JSModule.registerModule, JSModule.registerClass, or JSModule.registerFunc must not have duplicate names.
Incorrect example:
func addFloat() {} func addInt() {} let EXPORT_MODULE = JSModule.registerModule { runtime, exports => exports["addNumber"] = runtime.function(addFloat).toJSValue() exports["addNumber"] = runtime.function(addInt).toJSValue() // Will overwrite the first registered function addNumber }Functions, interfaces, and classes registered to JSModule using JSModule.registerModule, JSModule.registerClass, or JSModule.registerFunc must not have the same names as those decorated with
@Interop.Incorrect example:
@Interop[ArkTS] public func addNumber() : Unit {} func addFloat() {} let EXPORT_MODULE = JSModule.registerModule { runtime, exports => exports["addNumber"] = runtime.function(addFloat).toJSValue() // Will overwrite the @Interop-decorated function addNumber }