是否可以在C(而不是C++)中编写node.js扩展?
一个快速的谷歌搜索至少可以编写一个为node.js编写C++ "Hello World"的教程,但是目前还不清楚是否可以仅使用C编写这样的扩展。假设可能,我面临什么挑战/限制?是否可以在C(而不是C++)中编写node.js扩展?
如果需要,您可以用C语言编写扩展的部分代码,但您至少需要一小部分C++代码来将C代码与Node粘合在一起。
正如您将在HelloWorld中看到的那样,扩展依赖于v8.h
和node.h
标题,其中包含Node所需的所有类。如果没有这些,您将无法正确创建JS对象以导出回节点。也就是说,你可以非常轻松地编写一小组调用C函数并包装某种C结构的C++函数。
发现这个Hacker News上:
https://github.com/wesolows/v8plus
V8 +:节点附加C++到C边界
这层提供了一种方法用C来写,至少简单的节点插件,不用所有可怕的C++ goop,否则你可能会使用它。该goop仍然存在,但你不必写它。更重要的是,你可以在一个合理的编程环境中编写你的模块,避免混淆和容易出错的C++语义。
看起来像它不会工作的版本> Node.js 0.10,只是提出一个问题,找出肯定 –
需要在使用的extern申报个人的C函数的C++代码 “C” 语法
例子:
#define BUILDING_NODE_EXTENSION
#include <node.h>
extern "C" void f(int i, char c, float x);
using namespace v8;
如果你有多个C函数,那么就可以通过分组括号:
extern "C" {
void f(int i, char c, float x);
int g(char* s, char const* s2);
double sqrtOfSumOfSquares(double a, double b);
}
然后从C++函数调用的函数:
Handle<Value> MyFunction(const Arguments& args) {
HandleScope scope;
f(7, 'x', 3.14); // <---
return scope.Close(String::New("Hello"));
}
Handle<Value> CreateFunction(const Arguments& args) {
HandleScope scope;
Local<FunctionTemplate> tpl = FunctionTemplate::New(MyFunction);
Local<Function> fn = tpl->GetFunction();
fn->SetName(String::NewSymbol("theFunction")); // omit this to make it anonymous
return scope.Close(fn);
}
void Init(Handle<Object> target) {
target->Set(String::NewSymbol("createFunction"),
FunctionTemplate::New(CreateFunction)->GetFunction());
}
NODE_MODULE(addon, Init)
注意:使用示例代码Nodejs Addons
现在我们至少有3点不错的选择:
节点FFI: Node.js的外部函数接口
插件加载并调用动态使用纯JavaScript的库。它可用于而无需编写任何的C代码创建绑定本机库
https://github.com/node-ffi/node-ffi
痛饮:简单包裹生成
(它会产生许多语言包装,有什么解决一次许多问题)
http://www.swig.org/
emscripten
编译C和C++到运行甚至以接近原生速度的网络,而无需插件高度优化的JavaScript的。
http://kripken.github.io/emscripten-site/
如果你的模块使用libuv你可以将其链接到该节点的可执行文件。它以共享库的形式导出libuv函数。
然后你可以使用node-ffi来与它接口(这里不需要C++知识)。
这是我如何做它在Windows下使用MSVS:
testlib.c:
#include <stdio.h>
#include <stdlib.h>
#include "uv.h"
void (*p_callback)(int number, char *text);
void timer_cb1 (uv_timer_t* timer, int status) {
printf("libuv timer here\n", status);
p_callback(123, "it worked!");
}
void set_timer (int interval, void *pfunction) {
uv_loop_t *loop;
uv_timer_t *timer1;
printf("set_timer called. interval=%d callback=%p\n", interval, pfunction);
p_callback = pfunction;
printf("uv_version_string = %s\n", uv_version_string());
loop = uv_default_loop();
if (loop == 0) {
puts("could not get the reference to the default loop");
return;
}
puts("got the default loop. now allocating the timer struct");
timer1 = (uv_timer_t *) malloc(sizeof(uv_timer_t));
if (timer1 == 0) {
puts("malloc failed");
return;
}
puts("initializing timer");
uv_timer_init(loop, timer1);
puts("starting timer");
uv_timer_start(timer1, (uv_timer_cb) &timer_cb1, interval, interval);
puts("timer created. returning");
}
使用testlib.def:
EXPORTS set_timer
记住链接到node.lib
- 移动创建DLL来测试文件夹并在那里运行这些命令:
npm install ffi
(目前需要构建工具。检查指令)
node test-lib.js
测试lib.js是在这里:
var ffi = require('ffi');
var testlib = ffi.Library('testlib', {
'set_timer': [ 'void', [ 'int', 'pointer' ] ]
});
var callback = ffi.Callback('void', ['int', 'string'],
function(number, text) {
console.log("javascript callback here!!! number=" + number + " text=" + text);
}
);
console.log('registering the callback...');
testlib.set_timer(500, callback);
console.log('done')
发挥你的想象力。我们在libuv中有网络,工作线程和其他选项...
指向你的C++教程的链接将有助于 – lupz
https://www.cloudkick.com/blog/2010/aug/23/writing-nodejs-native -extensions/ – noahlz