C++与Nodejs的交互

来源:互联网 发布:mac 这个磁盘已被锁定 编辑:程序博客网 时间:2024/05/01 23:29

参考链接addon编写


待续

#include <node.h>#include <cstdlib>#include <ctime>#include <string>using namespace v8;// 函数返回 js 格式的 0 或 1Handle<Value> Random(const Arguments& args) {// 在每一个功能函数中,都会看到 HandleScope,主要是存放 handle 的容器// 管理 handle 的内存空间,当 handlescope 被销毁的时候// 内存将会释放,否则内存将会泄露HandleScope scope;// 确保函数中,在调用 scope.Close() 前都完成了出来// 当执行完 scope.Close 后,handle 将会被清空return scope.Close(Integer::New(rand() % 2));}/* 函数参数传入 */// 返回第 N 个数的斐波拉契数列// argument passedHandle<Value> Fibonacci(const Arguments& args) {HandleScope scope;// 检查参数个数问题if (args.Length() < 1) {return ThrowException(Exception::TypeError(String::New("First argument must be a number")));}// 将js格式转换成C语言可以使用的int32_t类型Local<Integer> integer = args[0]->ToInteger();int32_t seq = integer->Value();// 检测seq是否在正确值域上if (seq < 0) {return ThrowException(Exception::TypeError(String::New("Fibonacci sequence number must be positive")));}// 执行算法int32_t current = 1;for (int32_t previous = -1, next = 0, i = 0; i <= seq; i++){next = previous + current;previous = current;current = next;}// 返回数值return scope.Close(Integer::New(current));}/* 回调函数处理 */Handle<Value> Callback(const Arguments& args) {HandleScope scope;// 确保参数是回调函数,是函数if (!args[1]->IsFunction()) {return ThrowException(Exception::TypeError(String::New("Second argument must be a callback function")));}// 强制转换成函数Local<Function> callback = Local<Function>::Cast(args[1]);// nodejs默认第一个参数是错误情况,第二个参数是回调函数或参与工作的参数bool error = args[0]->BooleanValue();if (error) {Local<Value> err = Exception::Error(String::New("Something went wrong!"));// 为返回的错误,创建更多的属性,数值23err->ToObject()->Set(NODE_PSYMBOL("errno"), Integer::New(23));// 定义回调函数的参数个数和参数数组const unsigned argc = 1;Local<Value> argv[argc] = {err};// 异步回调执行 callbackcallback->Call(Context::GetCurrent()->Global(), argc, argv);} else {// 如果执行成功,Nodejs的惯例会将第一个参数设置成nullconst unsigned argc = 2;Local<Value> argv[argc] = {Local<Value>::New(Null()),Local<Value>::New(Integer::New(42))};callback->Call(Context::GetCurrent()->Global(), argc, argv);}return scope.Close(Undefined());// 异步函数,可以立即返回}/* 线程控制 */// 声明函数Handle<Value> Async(const Arguments& args);void AsyncWork(uv_work_t* req);void AsyncAfter(uv_work_t* req);// 构建一个结构体存储异步工作的请求信息struct Baton{// 存放回调函数,使用Persisten来声明,让系统不会在函数结束后自动回收// 当回调成功后,需要执行dispose释放空间Persistent<Function> callback;// 错误控制,保护错误信息和错误状态bool error;std::string error_message;// 参数运行的参数int32_t result;};// 函数会在nodejs当中直接被调用,它创建了一个请求的对象和等待的时间表Handle<Value> Async(const Arguments& args) {HandleScope scope;if (!args[0]->IsFunction()) {return ThrowException(Exception::TypeError(String::New("First argument must be a callback function")));}// 强制将参数转换成函数变量Local<Function> callback = Local<Function>::Cast(args[0]);// Baton 负责管理的异步操作的状态信息,作为参数带进去异步回调数据的流程中Baton* baton = new Baton();baton->error = false;baton->callback = Persistent<Function>::New(callback);uv_work_t* req = new uv_work_t();req->data = baton;// 通过libuv进行操作的异步等待,可以通过libuv定义一个函数,当函数执行完成后回调// 在此可以定义需要处理的异步流程AsyncWork和执行完异步流程后的操作AsyncAfterint status = uv_queue_work(uv_default_loop(), req, AsyncWork, (uv_after_work_cb)AsyncAfter);assert(status == 0);return scope.Close(Undefined());}// 注意不能使用 google v8 的特性,需要用原生的C/C++来写// 因为它是调用另外一个线程去执行任务void AsyncWork(uv_work_t* req) {Baton* baton = static_cast<Baton*>(req->data);// 执行线程池中的工作baton->result = 42;}// 执行完任务,进行回调的时候,返回到 v8/js 的线程// 这就意味着我们需要利用 HandleScope 来管理空间void AsyncAfter(uv_work_t* req) {HandleScope scope;Baton* baton = static_cast<Baton*>(req->data);if (baton->error) {Local<Value> err = Exception::Error(String::New(baton->error_message.c_str()));// 准备回调函数的参数const unsigned argc = 1;Local<Value> argv[argc] = {err};// 用类似 try catch 的方法,捕捉回调中的错误,在Node环境中// 可以利用process.on('uncaughtException')捕捉错误TryCatch try_catch;baton->callback->Call(Context::GetCurrent()->Global(), argc, argv);if (try_catch.HasCaught()) {node::FatalException(try_catch);}} else {const unsigned argc = 2;Local<Value> argv[argc] = {Local<Value>::New(Null()),Local<Value>::New(Integer::New(baton->result))};TryCatch try_catch;baton->callback->Call(Context::GetCurrent()->Global(), argc, argv);if (try_catch.HasCaught()) {node::FatalException(try_catch);}}baton->callback.Dispose();delete baton;delete req;}/* 对象处理 */// 注册模块功能,负责导出接口到 nodejsvoid RegisterModule(v8::Handle<v8::Object> target) {srand(time(NULL));target->Set(String::NewSymbol("random"), FunctionTemplate::New(Random)->GetFunction());target->Set(String::NewSymbol("fibonacci"), FunctionTemplate::New(Fibonacci)->GetFunction());target->Set(String::NewSymbol("callback"), FunctionTemplate::New(Callback)->GetFunction());target->Set(String::NewSymbol("async"), FunctionTemplate::New(Async)->GetFunction());}// 注册模块名称,模块将编译成modulename.node文件NODE_MODULE(modulename, RegisterModule)


0 0
原创粉丝点击