如何在Windows上将静态库与node-gyp一起使用?

Mih*_*hai 6 c++ linker node.js node-gyp node-modules

我正在尝试使用链接静态库node-gyp,以便将其用作本机node插件。但是,当我运行时,node-gyp rebuild出现以下链接错误:

\n\n
error LNK2001: unresolved external symbol "double __cdecl mylibengine::criticalZvalue(double)" (?criticalZvalue@mylibengine@@YANN@Z)\n
Run Code Online (Sandbox Code Playgroud)\n\n

紧接着是:

\n\n
C:\\Users\\Mihai\\Desktop\\msp-addon\\build\\Release\\mylib-addon.node : fatal error LNK1120: 1 unresolved externals [C:\\Users\\Mihai\\Desktop\\mylib-addon\\build\\mylib-addon.vcxproj\n
Run Code Online (Sandbox Code Playgroud)\n\n

看起来binding.gyp像:

\n\n
{\n    \'targets\': [{\n        \'target_name\': \'mylib-addon\',\n        \'cflags!\': [ \'-fno-exceptions\' ],\n        \'cflags_cc!\': [ \'-fno-exceptions\' ],\n\n        \'include_dirs\': [\n            \'<!@(node -p \\"require(\\\'node-addon-api\\\').include\\")\',\n            \'<(module_root_dir)/dependencies/mylib/include/\'\n        ],\n\n        \'sources\': [\n            \'src/MyLibNode.cpp\'\n        ],\n\n        \'dependencies\': [\n            \'<!(node -p \\"require(\\\'node-addon-api\\\').gyp\\")\'\n        ],\n\n        \'libraries\': [\n            \'<(module_root_dir)/dependencies/mylib/lib/x64/libmylib.a\'\n        ],\n\n        \'defines\': [ \'NAPI_DISABLE_CPP_EXCEPTIONS\' ]\n    }]\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

看起来MyLibNode.cpp像这样:

\n\n
#include <napi.h>\n#include "engine.h"\n\nNapi::Object InitAll(Napi::Env env, Napi::Object exports)\n{\n    // Temporary check to make sure `libmylib.a` works.\n    mylibengine::criticalZvalue(.3);\n\n    return exports;\n}\n\nNODE_API_MODULE(mspaddon, InitAll)\n
Run Code Online (Sandbox Code Playgroud)\n\n

我确信链接器可以找到libmylib.a,因为当我更改库的名称(例如,更改为disabled.a)时,我收到一个不同的错误,指出无法打开输入文件。但是,它无法解析外部符号

\n\n

我在这里发现了一个类似的、未解答的问题。其他问题的答案表明将完整的库路径添加到libraries,但我认为这不是我的场景的问题。

\n\n

为什么无法node-gyp解析外部符号?

\n\n
\n\n

附加信息:

\n\n
    \n
  • 我运行的是 Windows 10
  • \n
  • 我通过尝试将其与 一起使用来测试该库是否有效g++,如下所述
  • \n
\n\n

我有以下项目结构:

\n\n
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80build\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80dependencies\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80mylib\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80include\n        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80lib\n            \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80x64\n
Run Code Online (Sandbox Code Playgroud)\n\n
    \n
  • 在里面dependencies/mylib/include我有一个名为的头文件engine.h,其中包含:
  • \n
\n\n
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80build\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80dependencies\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80mylib\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80include\n        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80lib\n            \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80x64\n
Run Code Online (Sandbox Code Playgroud)\n\n
    \n
  • 我里面dependencies/mylib/lib/x64有一个名为的静态库libmylib.a
  • \n
  • 在根目录中我有一个名为的文件,main.cpp其中包含:
  • \n
\n\n
#pragma once\n\nnamespace mylibengine\n{\n    double criticalZvalue(double quantile);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我可以将可执行文件中的库链接为:

\n\n
#include <iostream>\n#include <engine.h>\n\n\nint main()\n{\n    std::cout << "Main working." << "\\n";\n    std::cout << mylibengine::criticalZvalue(.3) << "\\n";\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

此时,运行main.exe就会正常输出:

\n\n
g++ -obuild/main main.cpp -Idependencies/mylib/include/ -Ldependencies/mylib/lib/x64/ -lmylib\n
Run Code Online (Sandbox Code Playgroud)\n

Mih*_*hai 1

在上面的问题中,静态库是使用安装中的libmylib.a编译的。但是,使用 Microsoft C 和 C++ (MSVC) 运行时库。g++mingw64node-gyp

似乎(即在 GitHub 上查看此问题node-gyp不支持mingw64. 在链接的问题中,有人指出

mingw 使用自己的名称修改方案,这使得互操作性变得不可能。

这也是这个问题中遇到的问题(即error LNK2001: unresolved external symbol)。解决方案是使用 Microsoft 工具链创建静态库,然后链接器将正确解析符号。