Mastering DevEco Studio: Efficiently Implementing Glue Code Between ArkTS and C++
1. Background Introduction
HarmonyOS primarily offers two development languages: ArkTS and C++.
ArkTS is the preferred main application development language for HarmonyOS. It extends the TypeScript (TS) ecosystem with additional features tailored for application development, maintaining the basic style of TS while enhancing static checks and analysis during development through standardized definitions. This improves program stability and performance. ArkTS is well-suited for efficient UI interface development scenarios.
-
C++ is supported through the NDK (Native Development Kit) toolset. The NDK is a collection of native APIs, corresponding compilation scripts, and toolchains provided by the HarmonyOS SDK, enabling developers to implement critical application functionalities using C or C++. The NDK only covers some of HarmonyOS's basic underlying capabilities, such as the C runtime base library (libc), graphics libraries, window systems, multimedia, compression libraries, and Node-API for cross-language interoperability between ArkTS/JS and C. It does not provide the complete capabilities of ArkTS/JS APIs. C++ is suitable for the following scenarios:
- Performance-sensitive scenarios, such as gaming and physics simulations, which are compute-intensive.
- Scenarios requiring the reuse of existing C or C++ libraries.
- Scenarios needing specialized libraries tailored to CPU features, such as Neon acceleration.
Some capabilities in HarmonyOS are only available through C++ interfaces, such as audio and video encoding/decoding. Notably, the latest HarmonyOS 5.0.1 version primarily introduces new capabilities through C APIs. To fully leverage HarmonyOS's capabilities and become a proficient HarmonyOS developer, mastering mixed development with ArkTS and C++ is essential.
Calling C++ from ArkTS involves a series of complex processes. This article focuses on introducing a one-click tool provided by DevEco Studio to generate cross-language "glue" code, helping developers improve efficiency.
2. ArkTS Calling C++ Methods Process
Similar to Android's JNI, HarmonyOS enables ArkTS to call C++ methods primarily through NAPI. This section uses a Native C++ project demo created in DevEco Studio to illustrate the process of ArkTS calling C++ methods. The following diagram shows the code structure after creating a Native C++ project:
The project mainly consists of three parts:
-
types:
-
Index.d.ts: Contains the C++ interfaces exposed to ArkTS. -
oh-package.json5: Specifies the dynamic library name and the path to theIndex.d.tsfile.
-
CMakeLists.txt: The C++ code build script.
napi_init.cpp: The C++ implementation code.
Developing a Native module generally involves implementing the corresponding modules mentioned above.
2.1 Declaring C++ Interfaces in Index.d.ts
The declared functions are used for both C++ implementation and ArkTS calls.
export const add: (a: number, b: number) => number;
2.2 Registering and Implementing Declared Methods in C++
First, register the methods declared in Index.d.ts in the NAPI's Init method:
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
napi_property_descriptor desc[] = {
{ "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr }
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END
napi_property_descriptor is an array that can implement multiple methods. In the example, the string "add" represents the add method declared in Index.d.ts, and the third parameter Add is the name of the method implemented in C++. Next, implement the Add method:
static napi_value Add(napi_env env, napi_callback_info info)
{
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
napi_valuetype valuetype0;
napi_typeof(env, args[0], &valuetype0);
napi_valuetype valuetype1;
napi_typeof(env, args[1], &valuetype1);
double value0;
napi_get_value_double(env, args[0], &value0);
double value1;
napi_get_value_double(env, args[1], &value1);
napi_value sum;
napi_create_double(env, value0 + value1, &sum);
return sum;
}
The structure of the NAPI implementation method is fixed. The return value must be napi_value, and the parameters must be napi_env and napi_callback_info. The method parses specific parameter information from napi_callback_info to implement the desired functionality.
2.3 Configuring the Dynamic Library Name and C++ Source List in CMakeLists.txt
add_library specifies the name of the compiled library and the list of C++ code files to be compiled:
add_library(entry SHARED napi_init.cpp)
For more information on this, refer to the CMake build tool documentation: https://cmake.org/
2.4 Calling the Declared Methods in ArkTS
Once implemented, you can call the corresponding methods in ArkTS:
// First, import the dynamic library:
import testNapi from 'libentry.so';
// Call the corresponding add method
hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3));
3. DevEco Studio's One-Click Generation of Glue Code
From the ArkTS calling C++ methods process outlined above, it's evident that the process is somewhat cumbersome, requiring handling in three places across two files. Is there a more convenient method? Don't worry; the highlight of this article is the cross-language code editing feature provided by DevEco Studio IDE.
DevEco Studio IDE offers two creation methods:
- Write function declarations in
Index.d.tsand generate C++ functions with one click. - Write C++ function declarations in a C++ header file and generate registration code with one click.
The following sections provide detailed explanations of each method.
3.1 Writing Function Declarations in Index.d.ts and Generating C++ Functions with One Click
After declaring methods in Index.d.ts, the IDE will prompt an error. Hovering over it will display the following prompt:
Clicking "Generate native implementation" will quickly generate the registration code and implementation code in C++:
This reduces three manual implementations to one, significantly improving efficiency by more than two-thirds.
3.2 Writing C++ Function Declarations in a C++ Header File and Generating Registration Code with One Click
To create registration code with one click via C++ function declarations, you first need to create a header file and declare methods within it:
Right-click the method and select "Generate":
Then, click on "NAPI":
The registration function and the corresponding NAPI function implementation are automatically generated:
The method declaration in Index.d.ts is also automatically generated:
With the IDE's assistance, writing cross-language "glue" code significantly improves efficiency. It's fair to say that this feature provided by DevEco Studio is quite impressive and considerate for developers.
There are three points to note:
- The header files supported for one-click code generation include
.hpp,.hxx,.hh, and.h. - The NAPI function declarations that can be quickly generated currently support parameter types such as
bool,int,string,void,float,double,std::array, andstd::vector. - If the project already has a
napi_init.cppfile, theInitfunction within it will be appended. If not, the IDE will automatically create it for you.
4. Enhancing NAPI Type Conversion Code Writing in C++ with AI
While the IDE's automatic generation of cross-language glue code greatly aids Native code development, some developers may still find the TODO code generated to be cumbersome, with many ArkTS and C++ cross-language conversion codes being template-heavy and tedious. Is there a way to improve efficiency?
Taking the automatically generated add code as an example:
static napi_value Add(napi_env env, napi_callback_info info)
{
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
napi_valuetype valuetype0;
napi_typeof(env, args[0], &valuetype0);
napi_valuetype valuetype1;
napi_typeof(env, args[1], &valuetype1);
double value0;
napi_get_value_double(env, args[0], &value0);
double value1;
napi_get_value_double(env, args[1], &value1);
napi_value sum;
napi_create_double(env, value0 + value1, &sum);
return sum;
}
This code requires parsing two int type parameters from napi_callback_info, performing the operation, and then generating an napi_value to return.
Since this cross-language data type conversion is part of the NAPI protocol, the DevEco CodeGenie plugin also provides excellent support. You can install the Genie plugin in DevEco Studio to help quickly generate C++ implementation code:
With just a few "TAB" key presses, the code is almost complete, and you can then implement your business logic as needed.
5. Conclusion
This article primarily introduced the implementation steps for Native C++ code and the cross-language code editing tools provided by DevEco Studio IDE. These tools enable developers to write only function declarations and generate corresponding initialization registration methods and C++ implementation methods with one click. We hope you will explore and experience these tools to enhance your development efficiency.









Top comments (0)