nodejs C/C++ Addons 中的指针操作
发布于 12 年前 作者 jifeng 8680 次浏览 最后一次编辑是 8 年前

刚看到这个标题的时候,大家会觉得比较奇怪,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][1]
 2. [编写nodejs原生扩展][2]
 3. [node-extension-examples][3]

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

6 回复

wow,C++要出马了!

三个参考文章的链接木有用啊……

虽然不是很懂,但是还是觉得很厉害的样子

这个主要有点偏后端了。

@jifeng markdown语法是[文字](http://url/)

回到顶部