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-gyp
和 npm 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());"
我想使用 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-gyp
和 npm 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());"