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

时间:2016-05-01 00:15:56

标签: c++ node.js opencv 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)

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

3 个答案:

答案 0 :(得分:7)

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

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

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

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

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

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

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

$ nm -C myaddon.node

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

$ ldd myaddon.node

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

只是最终的核选项,opencv似乎有相当多的库,你最好的方法就是将所有这些库连接起来以解决缺失的符号。使用pkgconfig获取所有这些库:

$ pkg-config --libs opencv

您可以使用

获取包含标志
$ pkg-config --cflags opencv

将这些东西放在binding.gyp中的适当位置。

答案 1 :(得分:0)

我有一个与此类似的问题,并且我的opencv安装错误(?)。重新安装即可解决问题。

答案 2 :(得分:0)

发现,如果“ #include something.h”中包含某些内容,则编译可以,但是如果我使用(在我的情况下)某些新实例(如“ new Something()”),则将显示“未定义符号”。因此,我应该在“ sources”部分的binding.gyp中包含“ something.cpp”:

"sources": [ "something.cpp" ]