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

Node app with C++ addon complains about undefined symbol at runtime

我有一个 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!有没有人对可能导致此未定义符号错误的原因有任何建议?

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

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

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

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

如果您在此处遇到 opencv 未定义错误,则意味着您 link 正在错误地使用库或根本没有。需要注意的一些事项是:

  • 如果你在某处的 "libraries" 元素中拥有所有 -lopencv_* 库 link 标志,如果你不这样做,你实际上并没有 linking opencv 但它不会通常没有 -z defs;
  • 的抱怨
  • 如果它正在 linking 与您正在使用的 headers 相对应的库(避免此类问题的最简单方法就是使用您的发行版的 opencv)。如果您需要使用已签出的 opencv 版本,您可以在 binding.gyp 中明确说明这些内容,方法是为包含和库搜索路径设置构建标志。

您可以使用 nm 来查看在您的最终节点插件中定义了哪些符号...任何具有 "U"(未定义)的内容都应在最终加载阶段可用。除非您静态 linked opencv,否则您应该仍然看到 opencv 符号未定义。所以调用:

$ nm -C myaddon.node

-C 将分解名称,如果您 link 编辑了共享库,您应该看到 cv::Feature2D 未定义。最后一步是检查加载库时将加载哪些库。使用 ldd 来执行此操作。

$ ldd myaddon.node

这将向您显示所有找不到的库。如果在这里找不到 opencv 库,则说明您还没有 linked 共享库。如果确实找到了这些库,它还会向您显示它在哪里找到它们(您可以使用这些路径来确保您使用的是签出的库)。

只是最后一个核选项,opencv 似乎有很多库,最好的办法是 link 所有这些库来解决丢失的符号。使用 pkgconfig 获取所有这些库:

$ pkg-config --libs opencv

您可以使用

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

把这些东西放在你 binding.gyp 的适当位置。

我遇到了类似的问题,我的opencv安装不好(?)。重新安装解决了问题。

发现如果“#include something.h”包含某些内容,那么编译将正常,但如果我使用(在我的情况下)一些新实例,如 "new Something()"。所以我应该在源代码部分的 binding.gyp 中包含 "something.cpp":

"sources": [ "something.cpp" ]