带有C++插件的节点应用程序在运行时抱怨未定义的符号

Col*_*son 2 c++ opencv node.js node-gyp

我有一个NodeJS应用程序,它调用一个实现一些OpenCV调用的本机插件.该node-gyp build命令成功,但每次我尝试运行服务器时,node app我得到:

Error: /home/cmaccess/SfMLocalization/VisionLocalizeServer/build/Release/localizeImage.node: undefined symbol: _ZNK2cv9Feature2D5emptyEv
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at bindings (/home/cmaccess/SfMLocalization/VisionLocalizeServer/node_modules/bindings/bindings.js:76:44)
    at Object.<anonymous> (/home/cmaccess/SfMLocalization/VisionLocalizeServer/routes/localize.js:28:37)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
Run Code Online (Sandbox Code Playgroud)

在我的生活中,我不能弄清楚为什么会这样.我检查了一个已知的良好版本并重新安装了OpenCV.我甚至没有cv::Feature2D在任何代码中明确使用!有没有人建议可能导致这个未定义的符号错误?

ben*_*eno 8

链接库并随后尝试加载它时,需要检查一些事项.例如,在Linux中,所有符号只需要在最终加载阶段(加载可执行文件)时可用,对于节点,这将是您运行节点并加载本机插件时.如果缺少符号,则强制节点addon构建失败,您必须-z defs作为node-gyp中的链接器选项传递.因此,您需要在binding.gyp中将以下内容添加到"link_settings"元素或适当的位置:

"ldflags": [
            "-Wl,-z,defs"
        ]
Run Code Online (Sandbox Code Playgroud)

如果您不知道如何编辑构建和链接,请查看node-gyp教程(类似于).

注意:看起来节点也会延迟许多内部的符号加载,所以不幸的是,你将获得v8内容的大量未定义符号.这可能是不可避免的,因为节点动态加载这些符号.您必须检查输出并将其传递给寻呼机或grep以查找opencv缺失符号.这个名字在这个阶段不会被破坏.完成后删除这些标志.

如果您在此处获得opencv未定义错误,则表示您正在错误地链接库或根本不链接库.需要注意的一些事项是:

  • 如果你在某个"库"元素中有所有-lopencv_*库链接标志,如果你没有,你实际上并没有链接opencv,但通常不会抱怨-z defs;
  • 如果它链接的库对应于您正在使用的标题(避免这些问题的最简单方法就是使用您的发行版的opencv).如果您需要在binding.gyp中使用已检出的opencv版本,可以通过为include和库搜索路径设置构建标志来明确这些事情.

您可以使用nm查看最终节点插件中定义的符号...预计在最终加载阶段可以使用"U"(未定义)的任何内容.除非您静态链接opencv,否则仍应将opencv符号视为未定义.所以打电话:

$ nm -C myaddon.node
Run Code Online (Sandbox Code Playgroud)

-C将解析名称,如果链接共享库,则应将cv :: Feature2D视为未定义.最后一步是检查加载库时将加载哪些库.使用ldd执行此操作.

$ ldd myaddon.node
Run Code Online (Sandbox Code Playgroud)

这将显示任何无法找到的库.如果未在此处找到opencv库,则表示尚未链接共享库.它还会向您显示找到库的位置(您可以使用这些路径确保使用已签出的库).

只是一个最终的核选项,opencv看起来有很多库,你最好的方法是链接所有库来解决丢失的符号.使用pkgconfig获取所有这些库:

$ pkg-config --libs opencv
Run Code Online (Sandbox Code Playgroud)

你可以得到包含标志

$ pkg-config --cflags opencv
Run Code Online (Sandbox Code Playgroud)

把那些东西放在binding.gyp中的适当位置.