nodejs C/C++ Addons 中的指针操作

      刚看到这个标题的时候,大家会觉得比较奇怪,nodejs是一门脚本语言,它又没有“指针”这个数据结构,怎么能操作指针呢 ?这个问题关键就是nodejs中的Buffers这个数据结构。

      背景

      自己做的一个项目需要是从网站上下载一个图片,然后用libjpeg这个C类库对图像进行操作。程序架构是用nodejs写一个主运行程序,用C++扩展来调用libjpeg类库并实现底层的算法。libjpeg的8d版本中已经有两个接口解析图片信息,分别是从文件中读取和从内存中读取。

EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile));

EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo,
unsigned char * inbuffer,
unsigned long insize));

     对应这两个接口,就有两套解决方案:1,先将图片下载到本地文件,然后再从本地文件读到内存; 2,直接将图片读取到本地内存。

     显而易见,第二种方案更优:节省了大量的磁盘IO,提升速度。那接下来的问题就是如何写nodejs的C++扩展,得到一块内存指针,这就需要buffers出马了。

     

     解决方案

     开始具体的解决方案之前需要先了解如何编写nodejs的C/C++扩展,还是比较简单的。没做过相关开发的同学可以参看以下文章:

     1. nodejs C/C++ Addon

     2. 编写nodejs原生扩展

     3. node-extension-examples

     nodejs中buffers是一个比较重要的数据结构,典型应用就是读取文件内容和发送http请求,它们都能到相关buffers。查看nodejs的源码就会发现有这样的api:

  static inline char* Data(v8::Handle<v8::Object> obj) {
return (char*)obj->GetIndexedPropertiesExternalArrayData();
}

static inline char* Data(Buffer *b) {
return Buffer::Data(b->handle_);
}

static inline size_t Length(v8::Handle<v8::Object> obj) {
return (size_t)obj->GetIndexedPropertiesExternalArrayDataLength();
}

static inline size_t Length(Buffer *b) {
return Buffer::Length(b->handle_);
}

     通过Data()函数得到buffer的内存指针,通过Length()得到这块内存的大小,非常有用吧。

     这样的话,只要nodejs程序得到buffer,然后转化为v8中的object对象,再从这个object对象中得到这块内存的指针和内存大小,接下来就可以进行想要的指针操作了。重要的代码如下:

    Local<Value> arg1 = args[0];

if (Buffer::HasInstance(arg1)) {
size_t size = Buffer::Length(arg1->ToObject());
char* bufferdata = Buffer::Data(arg1->ToObject());
//to do with size and bufferdata

return scope.Close(Number::New(size));
}
else{
return scope.Close(Number::New(-1));
}

     大功告成。

     完整的代码可以参见:https://github.com/jifeng/node-buffer-extends

     其他操作buffer的例子:https://github.com/bnoordhuis/node-buffertools/blob/master/buffertools.cc

 

posted @ 2012-03-02 23:55 lengyuhong 阅读(...) 评论(...) 编辑 收藏