2012-05-06 88 views

回答

15

如果需要,您可以用C語言編寫擴展的部分代碼,但您至少需要一小部分C++代碼來將C代碼與Node粘合在一起。

正如您將在HelloWorld中看到的那樣,擴展依賴於v8.hnode.h標題,其中包含Node所需的所有類。如果沒有這些,您將無法正確創建JS對象以導出回節點。也就是說,你可以非常輕鬆地編寫一小組調用C函數幷包裝某種C結構的C++函數。

2

直接與node.js交互的代碼需要用C++編寫。

可能編寫使用不透明的類型從node.hv8.h需要的一切extern "C"包裝,但它可能更容易,只需使用C++而不是(其中,當然,可以叫出爲C代碼)。

8

發現這個Hacker News上:

https://github.com/wesolows/v8plus

V8 +:節點附加C++到C邊界

這層提供了一種方法用C來寫,至少簡單的節點插件,不用所有可怕的C++ goop,否則你可能會使用它。該goop仍然存在,但你不必寫它。更重要的是,你可以在一個合理的編程環境中編寫你的模塊,避免混淆和容易出錯的C++語義。

+0

看起來像它不會工作的版本> Node.js 0.10,只是提出一個問題,找出肯定 –

5

需要在使用的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

5

現在我們至少有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/

0

如果你的模塊使用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中有網絡,工作線程和其他選項...

相關問題