是否可以在C(而不是C++)中编写node.js扩展?

问题描述:

一个快速的谷歌搜索至少可以编写一个为node.js编写C++ "Hello World"的教程,但是目前还不清楚是否可以仅使用C编写这样的扩展。假设可能,我面临什么挑战/限制?是否可以在C(而不是C++)中编写node.js扩展?

+2

指向你的C++教程的链接将有助于 – lupz

+0

https://www.cloudkick.com/blog/2010/aug/23/writing-nodejs-native -extensions/ – noahlz

如果需要,您可以用C语言编写扩展的部分代码,但您至少需要一小部分C++代码来将C代码与Node粘合在一起。

正如您将在HelloWorld中看到的那样,扩展依赖于v8.hnode.h标题,其中包含Node所需的所有类。如果没有这些,您将无法正确创建JS对象以导出回节点。也就是说,你可以非常轻松地编写一小组调用C函数并包装某种C结构的C++函数。

直接与node.js交互的代码需要用C++编写。

可能编写使用不透明的类型从node.hv8.h需要的一切extern "C"包装,但它可能更容易,只需使用C++而不是(其中,当然,可以叫出为C代码)。

发现这个Hacker News上:

https://github.com/wesolows/v8plus

V8 +:节点附加C++到C边界

这层提供了一种方法用C来写,至少简单的节点插件,不用所有可怕的C++ goop,否则你可能会使用它。该goop仍然存在,但你不必写它。更重要的是,你可以在一个合理的编程环境中编写你的模块,避免混淆和容易出错的C++语义。

+0

看起来像它不会工作的版本> 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:

  • 创建MSVS一个新的DLL解决方案
  • 下载libuv,复制包括和LIB文件到MSVS
  • 下载node.lib文件并将其放入MSVS的lib文件夹中
  • 编译下面的示例源,它为主事件循环添加了一个定时器

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中有网络,工作线程和其他选项...