JavaScript 的 SWIG:"Module did not self-register." 正在加载

SWIG for JavaScript: "Module did not self-register." on load

我想使用 SWIG 3.0.12 和节点 8.12.0 从一些最小代码库创建一个本地模块:

api.h:

#pragma once
#include <string>
std::string foo();

api.cpp:

#include "api.h"
std::string foo() {
  return "hello world";
}

api.i:

%module(directors="1") api
%{
#include <api.h>
%}
%include "api.h"

构建节点模块 I 运行:

swig -c++ -javascript -node api.i
g++ -c -fPIC api_wrap.cxx api.cpp  -I /usr/include/node -I .
g++ -shared *.o -o api.node   

.. 并尝试导入它:

node -e "api = require('./api.node');"

但现在我明白了

module.js:682
  return process.dlopen(module, path._makeLong(filename));
                 ^

Error: Module did not self-register.
    at Object.Module._extensions..node (module.js:682:18)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Module.require (module.js:597:17)
    at require (internal/module.js:11:18)
    at [eval]:1:7
    at ContextifyScript.Script.runInThisContext (vm.js:50:33)
    at Object.runInThisContext (vm.js:139:38)
    at Object.<anonymous> ([eval]-wrapper:6:22)

我发现了很多关于类似错误的问题和答案,但它们似乎都与 npm 和节点模块的错误版本以及节点 运行time 有关。

我做错了什么?

遗憾的是,swig (3.0.12) 的当前版本不支持 Node.js 版本 7 或更高版本。相反,你会得到像 error: no template named 'WeakCallbackData' in namespace 'v8'

这样的编译时错误

要在 Node 8 上使用 swig,要么使用 master 分支,即 swig 的更高版本(看起来这将在下一个版本中修复,可能是 3.0. 13), 或下载 PR 968 中更改的 4 个文件并安装它们以代替 swig 3.0.12 附带的文件。在我的 Mac 上,这些文件位于 /usr/local/Cellar/swig/3.0.12/share/swig/3.0.12/javascript/v8/

虽然在那之后,@frans 仍然有一些工作要做。

根据 SWIG documentation、"it is crucial to compile your module using the same compiler flags as used for building v8",他们建议使用 node-gyp 构建模块。

您需要像这样创建一个 binding.gyp

{
  "targets": [
    {
      "target_name": "api",
      "sources": [ "api.cpp", "api_wrap.cxx" ]
    }
  ]
}

然后,在使用 swig 创建包装器之后,使用

构建模块
 node-gyp configure build

(如有必要,安装 node-gypnpm install -g node-gyp

您可能也不希望 %module(directors="1") 用于 JavaScript,并且您不应该对自己的头文件使用括号样式 include <file.h>

另外,如果你想使用std::string,你需要在你的接口文件中包含std_string.i

我建议你的api.i会更好

%module api
%{
#include "api.h"
%}

%include "std_string.i"
%include "api.h"

最后,当你完成后,模块将在 ./build/Release,所以用

进行测试
node -e "api = require('./build/Release/api.node'); console.log(api.foo());"