ArkTS调用C++类中的成员函数

ArkTS调用C++类中的成员函数

HarmonyOS
2024-05-28 21:43:35
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
海不辞水

ArkTS调用C++类中的成员函数,其中成员函数分为普通函数和静态成员函数,区别是普通成员函数需要创建一个ArkTS实例与C++实例绑定,而静态函数不需要。

在C++中定义一个类

class AddClass { 
public: 
    AddClass(std::string name) 
    { 
      this->instName = name; 
    }; 
    AddClass(){}; 
    ~AddClass(){}; 
 
    std::string instName; 
    double Add(double a, double b) 
    { 
     return a+b; 
    }; 
    static double StaticAdd(double a, double b) { return a + b; }; 
};

为这个类绑定构造函数:

static napi_value JsConstructor(napi_env env, napi_callback_info info) { 
    // 创建napi对象 
    napi_value jDemo = nullptr; 
 
    size_t argc = 1; 
    napi_value args[1] = {0}; 
 
    // 获取构造函数入参 
    napi_get_cb_info(env, info, &argc, args, &jDemo, nullptr); 
 
    // args[0] js传入的参数 
    char name[50]; 
    size_t result = 0; 
    napi_get_value_string_utf8(env, args[0], name, sizeof(name) + 1, &result); 
 
    // 创建C++对象 
    AddClass *cDemo = new AddClass(name); 
    //OH_LOG_INFO(LOG_APP, "%{public}s", (cDemo->instName).c_str()); 
 
    // 设置js对象name属性 
    napi_set_named_property(env, jDemo, "name", args[0]); 
 
    // 绑定JS对象与C++对象 
    napi_wrap( 
        env, jDemo, cDemo, 
        // 定义js对象回收时回调函数,用来销毁C++对象,防止内存泄漏 
        [](napi_env env, void *finalize_data, void *finalize_hint) { 
            AddClass *cDemo = (AddClass *)finalize_data; 
            delete cDemo; 
            cDemo = nullptr; 
        }, 
        nullptr, nullptr); 
    return jDemo; 
}

这个C++类将与ArkTS侧的类绑定,在ArkTS侧的类创建时,这个C++的构建函数也将调用

为类中普通函数Add()提供js侧接口:

static napi_value JsAdd(napi_env env, napi_callback_info info) { 
    size_t argc = 2; 
    napi_value args[2] = {nullptr}; 
    napi_value jDemo = nullptr; 
    napi_get_cb_info(env, info, &argc, args, &jDemo, nullptr); 
    AddClass *cDemo = nullptr; 
    // 将js对象转为c对象 
    napi_unwrap(env, jDemo, (void **)&cDemo); 
    // 获取js传递的参数 
    int value0; 
    napi_get_value_int32(env, args[0], &value0); 
    int value1; 
    napi_get_value_int32(env, args[1], &value1); 
    int cResult = cDemo->Add(value0, value1); 
    napi_value jResult; 
    napi_create_int32(env, cResult, &jResult); 
    return jResult; 
}

为类中静态函数StaticAdd()提供js侧接口:

static napi_value JsStaticAdd(napi_env env, napi_callback_info info) { 
    size_t argc = 2; 
    napi_value args[2] = {nullptr}; 
    napi_value jDemo = nullptr; 
    napi_get_cb_info(env, info, &argc, args, &jDemo, nullptr); 
    // 获取js传递的参数 
    int value0; 
    napi_get_value_int32(env, args[0], &value0); 
    int value1; 
    napi_get_value_int32(env, args[1], &value1); 
    int cResult = AddClass::StaticAdd(value0, value1); 
    napi_value jResult; 
    napi_create_int32(env, cResult, &jResult); 
    return jResult; 
}

通过对比可以发现普通函数,需要绑定一个C++类的实例,而静态函数不需要。

在init函数中暴露C++的类,和类中的函数,并引入ArkTS侧对应要绑定的类:

static napi_value Init(napi_env env, napi_value exports) { 
 
    // 定义模块需要对外暴露的方法 
 
 
    // 通过napi_define_class建立JS类与C++侧的映射关系,然后将对应的对象挂载到export上 
    napi_property_descriptor classProp[] = {{"Add", nullptr, JsAdd, nullptr, nullptr, nullptr, napi_default, nullptr}, 
                                            {"StaticAdd", nullptr, JsStaticAdd, nullptr, nullptr, nullptr, napi_static, nullptr}}; 
 
    napi_value jDemo = nullptr; 
    const char *jDemoName = "AddClass"; 
    // 建立JS构造函数与C++方法的关联,指定2个prop 
    napi_define_class(env, jDemoName, sizeof(jDemoName), JsConstructor, nullptr, 
                      sizeof(classProp) / sizeof(classProp[0]), classProp, &jDemo); 
    napi_set_named_property(env, exports, jDemoName, jDemo); 
    return exports; 
}

在index.d.ts中导出AddClass:

export const add: (a: number, b: number) => number; 
declare namespace testNapi { 
 
 
  class AddClass { 
    constructor(name:string) 
    name: string 
    Add(a: number, b: number): number 
    static StaticAdd(a: number, b: number): number 
  } 
 
 
 
} 
 
export default testNapi;

在ArkTS侧调用native侧类函数:

import hilog from '@ohos.hilog'; 
import testNapi from 'libentry.so'; 
 
@Entry 
@Component 
struct Index { 
  @State message: string = 'Hello World'; 
 
  build() { 
    Row() { 
      Column() { 
        Text(this.message) 
          .fontSize(50) 
          .fontWeight(FontWeight.Bold) 
          .onClick(() => { 
            //调用构造函数,获取对象 
            let AddClass = new testNapi.AddClass("class name"); 
            hilog.info(0x0000, 'ckTest', 'Test NAPI 3 + 7 = %{public}d', AddClass.Add(3, 7)); 
          }) 
        Button('static add') 
          .onClick(() => { 
            hilog.info(0x0000, 'ckTest', 'Test NAPI static 8 + 5 = %{public}d', testNapi.AddClass.StaticAdd(5,8)); 
          }) 
      } 
      .width('100%') 
    } 
    .height('100%') 
  } 
}

通过对比可以发现,类中的普通函数需要创建一个ArkTS类实例并通过绑定来调用C++类的够着函数来在native侧创建一个对应C++类,在调用类函数时通过类实例来调用。而static函数就不需要创建ArkTS类实例和C++实例,可以直接调用。

分享
微博
QQ
微信
回复
2024-05-29 23:02:56
相关问题
C++调用ArkTS 定义方法
1617浏览 • 1回复 待解决
Native调用ArkTS函数
815浏览 • 1回复 待解决
c/c++层主动调用ArkTS存在问题
220浏览 • 1回复 待解决
ArkTSC++互相直接调用
1682浏览 • 1回复 待解决
c++实例化自定义调用方法
187浏览 • 1回复 待解决
HarmonyOS ArkTSC/C++交互
417浏览 • 1回复 待解决
如何在C/C++ 创建ArkTS对象
2027浏览 • 1回复 待解决
如何为 C++ 提供回调函数
2263浏览 • 1回复 待解决
ArkTSC++之间交互
1129浏览 • 1回复 待解决
如何实现ArkTSC/C++HashMap转换?
928浏览 • 0回复 待解决
如何实现ArkTSC/C++数组转换
469浏览 • 1回复 待解决