在napi模块中定义枚举类型
枚举类型不是js的原生类型,它是ts中独有的语法,但是napi方法仅支持操作js对象。
下文将提供一个demo用来实现一个js的enum类。
分析ts枚举类的实现方式
定义一个ts枚举类
TypeScript 代码如下:
enum EnumClass {
VAL_A = 0,
VAL_B,
VAL_C,
}
使用tsc
命令将ts文件转为js文件,生成的js文件内容如下:
var EnumClass;
(function (EnumClass) {
EnumClass[EnumClass["VAL_A"] = 0] = "VAL_A";
EnumClass[EnumClass["VAL_B"] = 1] = "VAL_B";
EnumClass[EnumClass["VAL_C"] = 2] = "VAL_C";
})(EnumClass || (EnumClass = {}));
分析代码,tsc
转换后的代码逻辑如下:
- 定义一个全局变量
EnumClass
。 - 构造一个匿名函数,该函数接受一个入参,入参类型经推断应为Object。函数逻辑如下:
- 为Object EnumClass定义了三个
key
为enum的key
、value
为enum的value
的属性。 - 为Object EnumClass定义了三个
value
为enum的key
、key
为enum的value
的属性。
- 为Object EnumClass定义了三个
- 将全局变量EnumClass传递到上述函数,若全局变量EnumClass为undefined或null等值(即或语句前条件为false)则使其为空Object。
根据以上步骤,不难发现,enum在js中实际上是一个key、value互相作为key/value的Object。
使用napi方法进行实现js枚举类
定义一个C/C++的枚举类,其将作为js枚举类在Native枚举类的映射
enum EnumClass {
VAL_A = 0,
VAL_B,
VAL_C,
};
创建一个js Object, 用以容纳枚举类的内容
napi_value enumObject = nullptr;
napi_create_object(env, &enumObject);
定义两个下文将会使用到的宏,减少模板代码
// 按照枚举值的 key 和 value 创建对应的 napi value
#define GEN_ENUM_KV(env, enum, key, jsKey, jsVal) do { \
napi_create_string_utf8((env), #key, NAPI_AUTO_LENGTH, &(jsKey)); \
napi_create_int32((env), enum::key, &(jsVal)); \
} while (0)
// 用以减少定义 napi_property_descriptor 模板代码
#define SET_ENUM_KV(jsKey, jsVal) \
{ nullptr, (jsKey), nullptr, nullptr, nullptr, (jsVal), napi_default, nullptr }
创建并初始化所需的 napi_value
napi_value enumKeys[3] = {nullptr}; // 3: num of EnumClass
napi_value enumVals[3] = {nullptr}; // 3: num of EnumClass
GEN_ENUM_KV(env, EnumClass, VAL_A, enumKeys[0], enumVals[0]);
GEN_ENUM_KV(env, EnumClass, VAL_B, enumKeys[1], enumVals[1]);
GEN_ENUM_KV(env, EnumClass, VAL_C, enumKeys[2], enumVals[2]); // 2: index array
枚举类的实现应用到js Object
// 创建一个 napi_property_descriptor 数组,用以容纳js枚举值
napi_property_descriptor desc[] = {
NAPI_SET_VALUE(enumKeys[0], enumVals[0]),
NAPI_SET_VALUE(enumKeys[1], enumVals[1]),
NAPI_SET_VALUE(enumKeys[2], enumVals[2]), // 2: index array
};
napi_define_properties(env, enumObject, sizeof(desc) / sizeof(desc[0]), desc);
napi_set_property(env, enumObject, enumVals[0], enumKeys[0]),
napi_set_property(env, enumObject, enumVals[1], enumKeys[1]),
napi_set_property(env, enumObject, enumVals[2], enumKeys[2]), // 2: index array
完整示例代码
Native侧 C++ 代码。
enum EnumClass {
VAL_A = 0,
VAL_B,
VAL_C,
};
#define GEN_ENUM_KV(env, enum, key, jsKey, jsVal) do { \
napi_create_string_utf8((env), #key, NAPI_AUTO_LENGTH, &(jsKey)); \
napi_create_int32((env), enum::key, &(jsVal)); \
} while (0)
#define NAPI_SET_VALUE(jsKey, jsVal) \
{nullptr, (jsKey), nullptr, nullptr, nullptr, (jsVal), napi_default, nullptr}
static SomeFunction(napi_env env /* args... */)
{
// ... ...
napi_value enumObject = nullptr;
napi_create_object(env, &enumObject);
napi_value enumKeys[3] = {nullptr}; // 3: num of EnumClass
napi_value enumVals[3] = {nullptr}; // 3: num of EnumClass
GEN_ENUM_KV(env, EnumClass, VAL_A, enumKeys[0], enumVals[0]);
GEN_ENUM_KV(env, EnumClass, VAL_B, enumKeys[1], enumVals[1]);
GEN_ENUM_KV(env, EnumClass, VAL_C, enumKeys[2], enumVals[2]); // 2: index array
napi_property_descriptor desc[] = {
NAPI_SET_VALUE(enumKeys[0], enumVals[0]),
NAPI_SET_VALUE(enumKeys[1], enumVals[1]),
NAPI_SET_VALUE(enumKeys[2], enumVals[2]), // 2: index array
};
napi_set_property(env, enumObject, enumVals[0], enumKeys[0]),
napi_set_property(env, enumObject, enumVals[1], enumKeys[1]),
napi_set_property(env, enumObject, enumVals[2], enumKeys[2]), // 2: index array
napi_define_properties(env, enumObject, sizeof(desc) / sizeof(desc[0]), desc);
// ... ...
}
对应的枚举类的 .d.ts
描述文件。
export enum EnumClass {
VAL_A = 0,
VAL_B,
VAL_C,
}
与上述逻辑相匹配的js代码。
const EnumClass = {
0: "VAL_A",
1: "VAL_B",
2: "VAL_C",
VAL_A: 0,
VAL_B: 1,
VAL_C: 2,
}
标签:EnumClass,VAL,ts,enumVals,枚举,env,enumKeys,napi
From: https://www.cnblogs.com/milkpotatoes/p/18286305