• nodejs c++ 插件编译踩坑记


    写这篇文章的目的,是为了记录nodejs c++开发过程中踩到的坑,以及解决办法,以备以后回顾。

    这里我只记录了windows下开发过程中遇到的问题,linux下的,以后有机会,或者碰到了再记录吧。

    首先,大家需要记住,不要被一些报错吓到了,其实如果是一个有经验的c/c++开发者,有些问题其实并不难想到原因是什么,无非就是版本问题、符号问题等等。简单来说,在windows下,使用gyp,会生成一个ms vc工程,我们可以用visual studio打开它,然后编译,这样你可能会觉得熟悉些,好了,让我来解释一些概念或知识点吧(个人经验不是很足,有不对的地方,希望在评论里指出,谢谢)

    一,编译后的c++插件是否能用,和node-gyp版本有没有关系?

    没有关系。

    node-gyp只是一个构建工具,它会生成ms vc工程,最后利用微软的c++编译器,编译生成最终的c++插件,即一个动态库文件。

    二,windows下,设置msvs_version有什么影响?

    例如很多文章都说要设置为2015,2017等等,我设为2019可不可以?

    当然可以,没什么问题。唯一的影响就是,如果插件里使用了特定的函数,那么你发布后,可能还需要给别人安装相应的c++环境。

    三,node版本对构建有无影响?

    这个影响就大了,非常大!

    首先大家都知道,nodejs c++插件开发,有很多种方式,例如nan方式,napi(Node-API)方式,以及node-addon-api方式,或者你直接引用原始的v8、uv库。常用的是napi方式,这种方式是ABI化的,但是有版本的区分,截取官方的一张图:

    可以看到,不同版本的napi(横轴1,2,3。。。),在不同版本的node下得到支持(纵轴第一列)

    插件的作者(或者你),在开发时的本机环境,可能与使用者是不一样的,所以有时候下载的插件不能通过编译而报错,那么其中之一的检查项,就是检查插件的node api版本。万一作者没写,那就只能一个个试了。(提示,可以安装nvm来切换nodejs版本)

    查看本机napi版本的方式:

    如图所示,我当前使用的,是 v14.20.0版nodejs,它的napi是8。

     当然,如果你的napi版本高于你要测试的版本,例如你的版本是8,你想测试版本3行不行,可以直接在c++预定义符里指定

    当然如果你的nodejs的napi版本本身就低于插件所需要的版本,那就只能升级nodejs了。这也是编译报错的原因之一。

    这个问题解释也很简单,搞过c/c++开发的都知道,引入第三方库的时候,可以静态引入,也可以动态引入。静态引入,需要一个头文件,需要一个静态库(lib),最后编译时,还需要连接到真正的实现。不过头文件可能是最新的,而静态库可能不是最新的,那么node的作者,就在头文件里指定了NAPI_VERSION的版本,来启用不同的函数:

     

    这里尤其是在electron里引用了c++插件时,需要注意这个问题,因为electron内集成的node,和官方的node版本其实是不完全一样的,除了上述NAPI_VERSION以外,还要注意abi的版本,因为这个限定了API调用的约定,如果不一致,那么即便你编译插件通过了,实际运行electron程序时,依然会报错。

    关于electron下引用c++插件,首先要说明的是,你必须注意你的编译环境,即你本机运行的node,和electron内置的node的环境,即运行时环境。这两个环境是不一样的。其次,你可以直接用electron的环境来编译(以下举例,是用electron的环境来编译插件)。

    看一下如何查看electron的node环境,除了查看官方文档外,还可以先运行起electron来查看。由于electron编译时,需要下载原始的electron包,那么我们可以找到该包,直接运行electron来查看。此包默认下载到了 C:\Users\用户名\AppData\Local\electron\Cache 下,打开该目录下的dos窗口,然后运行 electron -a ,就可以查看 abi 版本了。其他命令有

     electron 的 abi 版本,对应本机 node 的 abi 版本字段是:process.versions.modules

     所以,如果你需要编译c++插件,以用于electron,那么在编译时,需要指定运行时环境:

    假设你用的 node-gyp 构建

    node-gyp rebuild --target=10.1.7 --arch=x64 --dist-url=https://electronjs.org/headers

    其中,target即electron的版本,arch即运行时架构,默认就是x64,后面的dist-url,用于告诉node-gyp,哪里去下载头文件、静态库等资源。

    这条命令可以放到插件的脚本里运行。

    假设你用的 node-pre-gyp 构建,命令和上述差不多

    node-pre-gyp rebuild --target=10.4.7 --dist-url=https://electronjs.org/headers --runtime=electron

    这里,我在后面指定了runtime为electron,其实不指定,差不多也可以,除非你构建的环境是早期的nodejs(NAPI_VERSION小于3),否则就是兼容的。

    待续。。。。。。

  • 相关阅读:
    为什么使用ioutil.ReadAll 函数需要注意
    【JAVA程序设计】(C00085)基于Servlet+jsp的图书信息管理
    Flutter TapGestureRecognizer 如何工作
    数学建模比赛中常用的建模提示词(数模prompt)
    随机手机号查询易语言代码
    国际航运管理考试整理
    react简述-react基础-jsx语法-jsx表达式-jsx动态属性-jsx列表渲染
    浅析目标检测入门算法:YOLOv1,SSD,YOLOv2,YOLOv3,CenterNet,EfficientDet,YOLOv4
    STM32的外部SRAM
    2022win7cf烟雾头最新调法
  • 原文地址:https://blog.csdn.net/novaliang/article/details/127861317