我有一个具有此功能的C库clib.c
int hi(char* hello) { return 900; }
编译为:
gcc clib.c -o clib.so --shared -fPIC
我正在Nim libray中使用它,名为'nlib.nim`:
proc hi*(hello: cstring): cint {.cdecl, importc: "hi", dynlib: "./clib.so".}
proc hi2*(hello: cstring): cint {.cdecl, exportc.} = return hi(hello)
表示为:
nim c --app:lib --noMain -o:nlib.so nlib.nim
如果我直接在Nim中调用hi2函数,它将完美返回900。但是,如果我通过FFI从NodeJS调用它:
var ffi = require('ffi');
var lib = ffi.Library('./nlib.so', { 'hi2' : [ "int", ["string"] ] });
console.log(lib.hi2("hey"));
我得到一个Segmentation fault (core dumped)
。
答案 0 :(得分:1)
您的代码中有两个问题:
您不应该使用--noMain
。
在nlib.so
库初始化期间,它将动态地(即使用clib.so
和dlopen
加载dlsym
中的符号。指定--noMain
会干扰此过程,只有在您有特定目标时才应这样做。
从其他宿主语言调用Nim时,应初始化Nim GC。
通常通过调用setupForeignThreadGc
来完成。要使其可用,您应该使用--threads:on
进行编译。
因此,最终的解决方案如下所示:
# nlib.nim
proc hi*(hello: cstring): cint {.cdecl, importc: "hi", dynlib: "./clib.so".}
proc nlib_init* {.cdecl, exportc.} =
setupForeignThreadGc()
proc nlib_hi*(hello: cstring): cint {.cdecl, exportc.} =
return hi(hello)
编译为:
nim c --threads:on --app:lib -o:nlib.so nlib.nim
然后在node.js中,我们有:
# nlib.js
var ffi = require('ffi');
var nlib = ffi.Library('./nlib.so', {
'nlib_init': [ "void", []],
'nlib_hi': [ "int", ["string"] ]
});
nlib.nlib_init()
console.log(nlib.nlib_hi("hey"));
执行:
node nlib.js
输出:
900
答案 1 :(得分:0)
您不能在JS和C中同时使用FFI。 引用Nim in Action:
请务必注意,FFI允许您与C进行接口, C ++和Objective-C库位于同一应用程序中,但您不能 同时与C和Java Script库交互。这个 因为C ++和Objective-C都向后兼容C, 而JavaScript是一种完全不同的语言。