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

问题描述:

我有一个NodeJS应用程序,它可以对实现一些OpenCV调用的本机插件进行一些调用。该node-gyp build命令成功,但每次我尝试用node app运行服务器,我得到:使用C++插件的节点应用程序在运行时抱怨未定义的符号

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) 

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

链接库和然后尝试加载它时,有几件事要检查。例如,在Linux中,所有的符号只需要在最后的加载阶段(加载可执行文件)就可以得到,而当节点运行节点并加载本地插件时,这个节点就是可用的。如果缺少符号,强制节点插件构建失败,则必须通过-z defs作为node-gyp中的链接器选项。所以,你会在你的binding.gyp添加下面的“link_settings”元素或酌情:

"ldflags": [ 
      "-Wl,-z,defs" 
     ] 

请大家看一个节点GYP教程(类似this),如果你不知道如何编辑建设和联系。

注意:看起来节点也推迟了很多其内部的符号加载,所以不幸的是,你也会得到很多未定义的符号,用于v8的东西。当节点动态加载这些符号时,这可能是不可避免的。您将不得不检查输出并将其传输到寻呼机或grep以查找缺少opencv的符号。在这个阶段,名字不会被破坏。当你完成删除这些标志。

如果你在这里得到opencv未定义的错误,这意味着你错误地链接了库,或者根本没有链接库。有些事情看出来的是:

  • ,如果你把所有的-lopencv_ *库链接标志在“库”元素的地方,如果你没有,你实际上并没有连接OpenCV的,但它通常不会抱怨没有-z defs;
  • 如果它正在链接与您正在使用的头文件相对应的库(避免这些问题的最简单方法就是使用您的发行版的opencv)。如果您需要在binding.gyp中使用已检出的opencv版本,可以通过设置包含和库搜索路径的构建标志来清楚说明这些事情。

您可以使用nm来查看您的最终节点插件中定义了哪些符号......任何带有“U”(未定义)的东西预计将在最终加载阶段可用。除非静态链接opencv,否则您仍应该将opencv符号视为未定义。于是呼:

$ nm -C myaddon.node 

的-C将还原函数的名字,你应该看到的简历:: Feature2D为未定义如果您链接的共享库。最后一步是检查加载库时将加载哪些库。使用ldd来做到这一点。

$ ldd myaddon.node 

这会显示找不到的任何库。如果在这里找不到opencv库,那么您没有链接共享库。它还会告诉你它找到它们的位置(你可以使用这些路径来确保你使用的是检出的库)。

只是一个最终的核选项,opencv似乎有好几个库,你最好的办法就是把它们全部链接起来解决缺失的符号。获取所有这些库与pkgconfig:

$ pkg-config --libs opencv 

你可以得到包括标志与

$ pkg-config --cflags opencv 

把那东西在你binding.gyp适当的地方。

+1

感谢您的评论!我最终发现了这个问题。我以为我是连接到安装在/ opt/opencv中的OpenCV 3.0,但由于包含搜索路径中的路径顺序,它无意中链接到/ usr/local中的OpenCv 2.4。让我永远把它弄清楚。 –