本文是对NodeJS C++ Addons原生写法的进一步探索,介绍了利用原生的Node和V8提供的API实现类包装和异步调用的具体做法。在阅读本文之前,如果对NodeJS C++ Addons的基础不熟悉的话,建议先阅读上一篇博客【NodeJS C++ Addons基础】进行了解之后再回来阅读本文。
本文所使用的代码示例可以从该仓库中找到–【cpp-addons】
备注: 本文旨在探究NodeJS C++ Addons的原生写法,了解部分底层知识,所使用的NodeJS版本为8.11.1,由于V8原生的API会发生变动,不同版本的NodeJS的支持情况可能不同。因此不保证代码能兼容所有版本的NodeJS。
NodeJS C++插件可以提供接口给JavaScript使用,在上一篇博客【NodeJS C++ Addons基础】也已经给出不少示例。不过,在之前的示例中,实现的都是同步调用。按照之前的做法,JavaScript调用C++插件模块提供的接口后,会阻塞JavaScript代码的执行。同步调用带来的阻塞不符合JavaScript异步的特点,在遇到复杂耗时的任务时,这种阻塞更是严重影响应用的性能。为了解决这个问题,就需要实现异步调用,使得C++插件模块的接口在被调用后不会阻塞JavaScript的执行。
实现异步操作需要用到libuv这个库,libuv是一个跨平台的抽象库,它实现了Node.js的事件循环、工作线程、以及平台所有的的异步操作。利用libuv可以很方便地让C++插件模块的接口异步化。接下来将对上一篇博客【NodeJS C++ Addons基础】中的使用的累加求和的例子进行改进,实现异步调用。下面是改进后的代码,在注释中会对部分操作进行阐述。
#include #include #include namespace AsyncDemo {
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::Value;
using v8::Null;
using v8::Exception;
using v8::String;
using v8::Undefined;
using v8::Persistent;
using v8::HandleScope;
/* 存放数据供子线程使用的结构体 */struct Data {
/* 回调函数 */
Persistent callback;
/* 求和参数 */std::vector<double> args;
/* 求和结果 */double result;
};
/* 子线程执行的代码 */void calculate (uv_work_t* req) {
Data* data = static_cast(req->data);
/* 遍历参数进行求和 */
data->result = 0.0;
for (int i = 0; i < data->args.size(); ++i) {
data->result += data->args[i];
}
}
/* 子线程结束后执行的代码 */void calculateComplete (uv_work_t* req) {
Data* data = static_cast(req->data);
Isolate* isolate = Isolate::GetCurrent();
/* 必须创建一个HandleScope,否则后面无法创建句柄 */
HandleScope handleScope(isolate);
/* 将求和结果转换为一个JS Number */
Local argv[1] = { Number::New(isolate, data->result) };
/* 通过回调函数返回求和结果 */
Local cb = Local::New(isolate, data->callback);
cb->Call(Null(isolate), 1, argv);
/* 回调完成后清除资源 */
data->callback.Reset();
delete data;
delete req;
}
void accumulateAsync (const FunctionCallbackInfo& args) {
Isolate* isolate = args.GetIsolate();
/* 参数不合理异常 */if (args.Length() < 1) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "Arguments Number Error.")
));
return;
}
/* 没有回调函数 */if (!args[args.Length() - 1]->IsFunction()) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "No Callback Error.")
));
return;
}
/* 提取通过参数传递的回调函数 */
Local callback = Local::Cast(args[args.Length() - 1]);
/* 创建Data结构体存储数据 */
Data* data = new Data();
/* 存储回调函数 */
data->callback.Reset(isolate, callback);
/* 提取参数并存储到data */for (int i = 0; i < args.Length() - 1; ++i) {
/* 如果参数不是数字,向js抛出异常 */if (!args[i]->IsNumber()) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "Arguments Type Error.")
));
return;
} else {
data->args.push_back(args[i]->NumberValue());
}
}
/* 启动工作线程进行求和计算 */
uv_work_t *req = new uv_work_t();
req->data = data;
uv_queue_work(
uv_default_loop(),
req,
(uv_work_cb)calculate,
(uv_after_work_cb)calculateComplete
);
/* 本函数直接返回,无需等待线程计算完成 */
args.GetReturnValue().Set(Undefined(isolate));
}
void init (Local exports) {
NODE_SET_METHOD(exports, "accumulateAsync", accumulateAsync);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, init)
}
实现C++类和实例的包装,让JavaScript能够直接使用到C++类和实例,这个过程的操作虽然繁琐了一点,但也不是太难,中提供的API已经可以很方便地实现这个功能。实现C++插件接口的异步化,让JavaScript能够进行异步调用而不被阻塞,需要用到多线程的知识。在NodeJS官方文档中对如何使用libuv进行异步操作并没有相关例子展示,所以在写前面的例子的时候也比较折腾。libuv的API文档比较晦涩,幸好网上还有另一份介绍文档【An Introduction to libuv】,这份文档中除了对一些概念和API进行介绍之外,也会有给出代码示例,对初学者来说比较友好。
java的多态性是指main方法在调用属性的时候类可以对这一属性做出反应的情况
//package 1;
class A{
public void test(){
System.out.println("A");
}
}
class D extends A{
public void test(){
S
参考了网上的思路,写了个Java版的:
public class Fibonacci {
final static int[] A={1,1,1,0};
public static void main(String[] args) {
int n=7;
for(int i=0;i<=n;i++){
int f=fibonac
1、查看系统客户端,数据库,连接层的编码
查看方法: http://daizj.iteye.com/blog/2174993
进入mysql,通过如下命令查看数据库编码方式: mysql> show variables like 'character_set_%'; +--------------------------+------
public class MyQueue {
private long[] arr;
private int front;
private int end;
// 有效数据的大小
private int elements;
public MyQueue() {
arr = new long[10];
elements = 0;
front
A binary search tree (BST) is a binary tree where each node has a Comparable key (and an associated value) and satisfies the restriction that the key in any node is larger than the keys in all