实战C++addon
经过前面一段时间的学习,我对完成公司的任务已经信心满满,满以为自己能够顺利地完成任务了。可是没想到更多的困难还在后头。具体代码我就不贴了,但是我在这里将实际编写过程中遇到的困难和解决方法中我认为有意义的部分分享出来。
公司的任务是要求我二次封装一个静态链接库(.lib)文件,转而让它能被node.js使用。而该静态链接库可以提供一个结构体数组,这个结构体数组就是我们需要的数据,我们需要把它的数据分别转换为node.js能识别的形式。
结构体数组的转换
关于这个我走了一些弯路,曾经我还想着按转换类和对象的思路去走,结果做了不少无用功。后面想到,结构体数组的每一个元素都是一个结构体,而结构体可以理解为js里的一个对象!所以按我的思路结构体数组转换为node.js的形式应该是这样的:
{
{0,member1},
{1,member2}
}
因此我在.cc中使用了一个循环
Local<Object> obj_list = Object::New(isolate);
for(int i = 0; i < MAX_GRID_VRS; i++)
{
Local<Object> obj = Object::New(isolate);
obj->Set(0,String::NewFromUtf8(isolate,member1));
obj->Set(1,String::NewFromUtf8(isolate,member2));
obj_list->Set(i,obj);
}
这样就可以把结构体数组转化为node.js中的对象了。
具体数据转换
上一部分的代码就提到了,我需要把结构体中的成员转换为v8的string类型。
而这个函数是接受一个C++中的const char类型的参数。
而我得到的结构体中的成员是unsigned char类型的。我们知道unsigned char*类型是比较麻烦的,因为它是0~255,而一般的char是-127~127的。
因为本人的C++功底不太深厚,为此我特意查阅了不少资料,写了一个函数来解决这个问题。
void convertUnsignedToConstChar(const char* str,unsigned char* Unchar,int clen){
char* temp = new char[clen];
for(int i = 0; i < clen; i++)
{
sprintf(temp + i * 2, "%02x", Unchar[i]);
}
str = temp;
}
在.gyp中包含.lib文件的引用
gyp引用静态链接库需要用到libraries
关键字。
'libraries':['C:/Users/acer/Desktop/Mylib/MyDataTransfer.lib']
我这里使用了绝对路径,但是也可以用相对路径。
注意.lib的位数版本应与node的版本一致
这个是困扰我最久,也是最百思不得其解的问题。我明明.cc文件也没有语法错误了(编译过程没有报错,但是实际效果通不通过还不得而知),gyp中也引用了所需的lib了。但是它总是会报"无法解析的外部符号"
错误,这个错误熟悉C++的同学们都知道,很可能就是外部库没有正确引用的原因。
最后我在Stack Overflow上找到了类似的案例,我就用visual studio 2015自带的VS2015 x64 本机工具命令提示符工具检查这个.lib的位数版本。
dumpbin.exe /headers C:/Users/acer/Desktop/Mylib/MyDataTransfer.lib
键入上面命令后,我们就能在下面的FILE HEADER VALUES字段找到我们要的属性。
没错,我发现这个lib是32位的,我真是*了!
为此我又重新安装了32位的node,重新编译,终于通过了!
接下来可能会研究Nan和N-API的使用。