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
- NodeJS与Mysql的交互
- C++与Nodejs的交互
- nodejs 与mysql 交互
- Nodejs与MySQL交互
- nodejs与C++交互(二)
- NodeJs与MySQL交互数据
- nodejs 与redis交互说明
- Nodejs与Redis的交互(mranney/node_redis)入门
- 使用nodejs实现web服务器与客户端的交互
- java与c的交互
- lua 与c的交互
- Lua与C的交互
- Lua与C的交互
- lua与c的交互
- C与Lua的交互
- Lua的与C交互
- C#与C/C++的交互
- [总结]C与Shell程序的交互
- js注意事项
- iOS开发--通过storyboard查看源码
- TabBar的自动渲染为蓝色改成图片本身颜色
- 子集生成
- 利用intellijidea创建maven多模块项目
- C++与Nodejs的交互
- 在 Eclipse 中使用命令行
- 九度-题目1126:打印极值点下标
- hibernate缓存机制详细分析
- iOS 开发之动画篇 - Transform和KeyFrame动画
- 杭电1276士兵队列训练问题
- Linux vmstat命令实战详解
- Codeforces--630F--Selection of Personnel(组合数)
- gitlab 7.4.5 relative url configuration