【问题标题】:"The specified module could not be found" when using a custom nodejs addon使用自定义nodejs插件时“找不到指定的模块”
【发布时间】:2023-03-03 05:14:28
【问题描述】:

我正在编写一个依赖于 OpenGL (glfw) 的 nodejs 插件。它编译成功,但是当我尝试在节点中使用它时,我收到错误The specified module could not be found

这是插件 C++ 代码的问题部分:

#include <glfw/glfw3.h>

if(glfwInit()) {
    printf("glfw init success");
}
else {
    printf("glfw init failed");
}

在插件中使用这个,它会编译但会导致节点中的错误。没有它,它可以毫无问题地编译和运行。

这是我的 binding.gyp:

{
  "targets": [
    {
      "target_name": "engine",
      "sources": [
        "addon/addon.cc"
      ],
      "libraries": [
            "<(module_root_dir)/addon/lib/gl/glfw3dll.lib"
        ],
      "include_dirs": [
        "addon/lib",
        "<!@(node -p \"require('node-addon-api').include\")"
      ],
      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
    }
  ]
}

以及插件文件结构:

addon
  lib
    glfw
      glfw3.dll
      glfw3.h
      glfw3.lib
      glfw3dll.lib
      glfw3native.h
      opengl32.lib
  addon.cc

编辑: 新的 binding.gyp:

{
  "targets": [
    {
      "target_name": "engine",
      "sources": [
        "addon/addon.cc"
      ],
      "libraries": [
        "-lglfw3dll",
        "-lopengl32",
        "-L<module_root_dir)/lib/glfw",
        "-Wl,-rpath,\$$ORIGIN/../../lib",
        ],
      "include_dirs": [
        "addon/lib",
        '<!@(node -p "require(\'node-addon-api\').include")'
      ],
      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
    }
  ]
}

【问题讨论】:

  • 你如何尝试在节点中使用它?
  • @bmacnaughton 就像一个插件模块,带有const engine = require('bindings')('engine');。它可以在不包含任何外部库的情况下工作。
  • 文件是否存在? ls -R build在包根目录下?
  • @bmacnaughton 对不起,我可能应该澄清一下。我在运行插件时没有问题。我得到了插件编译和运行。当我添加 OpenGL 时它才开始崩溃。
  • 从本地位置加载库可能有点棘手。我将尝试提供一个示例作为答案-它可能会也可能不会解决您的问题。但我假设只有在您尝试加载 glfw3dll.lib 时它才开始失败。

标签: c++ node.js glfw node.js-addon node-addon-api


【解决方案1】:

我不确定这是您的问题,但说服加载程序在本地目录中加载特定库可能有点棘手。我将此部分添加到了 binding.gyp 中的 targets 数组中。

诀窍是告诉链接器查找相对于$ORIGIN(插件所在的位置)的库。因为插件在build/Release 中,所以$ORIGINbuild/Release../../ 让你回到模块根目录。

通过binding.gyp 和链接器的引用规则找到指定$ORIGIN 的正确方法只是反复试验。 \$$ORIGIN 导致 $ORIGIN 嵌入到节点插件中。

'conditions': [
    ['OS in "linux"', {
    # includes reference glfw3dll/glfw3dll.h, so
    'include_dirs': [
      '<!@(node -p "require(\'node-addon-api\').include")',
        '<(module_root_dir)/'
    ],
    'libraries': [
        '-lglfw3dll',
        '-L<(module_root_dir)/dir-for-glfw3dll/',
        '-Wl,-rpath-link,<(module_root_dir)/dir-for-glfw3dll/',
        '-Wl,-rpath,\$$ORIGIN/../../dir-for-glfw3dll/'
    ],
    }]
]

(我把我的文件名改成你的文件,放到module_root_dir直接下的一个目录下。)

【讨论】:

  • 我根据我的项目结构发布了我的新binding.gyp,不确定它是否完全正确。我在构建时收到错误:cannot open file 'glfw3dll.lib'。我也用-lglfw3 尝试过,我得到了同样的结果。
  • 也许"-Wl,-rpath,\$$ORIGIN/../../lib" 应该是"-Wl,-rpath,\$$ORIGIN/../../lib/glfw"。并确保您的模块结构是 /build/Release/engine.node
  • 仍然是同样的错误,engine.node 在该文件夹中,但现在在构建时失败,所以它不存在。
  • 很抱歉没有修复它。但如果它在构建时失败,那么 what 不存在?
【解决方案2】:

我设法让它与这个 binding.gyp 文件一起工作:

{
  "targets": [
    {
      "target_name": "engine",
      "sources": [
        "addon/addon.cc"
      ],
      "libraries": [
        "legacy_stdio_definitions.lib",
        "msvcrt.lib",
        "msvcmrt.lib",
        "<(module_root_dir)/addon/lib/glfw/opengl32.lib",
        "<(module_root_dir)/addon/lib/glfw/glfw3.lib"
        ],
      "include_dirs": [
        "addon/lib",
        '<!@(node -p "require(\'node-addon-api\').include")',
      ],
      'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ]
    }
  ]
}

【讨论】:

    【解决方案3】:

    以防万一其他人遇到同样的问题并在这里结束。插件所需的库需要在运行时触手可及,即使链接器设法找到它。

    例如,如果这是在 Windows 上,并且您在构建/链接期间与 foo.lib 链接,则在运行时,foo.dll 应该在同一个文件夹中(对我来说,它与 .node 在同一个文件夹中工作)或在路径中的文件夹中。否则它不会被加载并且会抛出这个错误。我认为非常无法解释的错误。

    此外,将库保存在与 .node 相同的文件夹中有助于分离不同的架构构建和依赖项(x86、x64 等)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-27
      • 1970-01-01
      • 2016-12-15
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 2021-09-12
      • 1970-01-01
      相关资源
      最近更新 更多