保存
×

准备了好久的NodeJS扩展开发最近终于慢慢走上正轨道,随着对V8 API 的逐渐熟悉,以及对NodeJS v0.11 前后两个版本的变动,通过NodeJS最新的源代码和V8的Sample,感觉上手起来还是很快的。同时对C++的感觉也越来越顺手,比如对template(解决了Handle的疑惑), class(能看懂nodejs源代码),reference(解决了const v8::FunctionCallbackInfo& info的疑惑) 等的了解。

本文记录一下开发一个node-desktop-notification扩展过程中的心得。采用了Gnome桌面的libnotify库, 用到的知识如下:

libnotify 和 libnotifymm

一开始参考archlinux wiki上的代码,看到C++的部分直接就拿过来用了,直接编译成功,运行报warnning,估计是没开桌面通知,死活没出来界面,中间以为不行直接放弃了,升级fedora20后试了一把居然OK了。

很顺利的就把代码嵌入到node addon中,但是编译始终报错

无奈之下尝试了一把C语言的版本,居然直接编译通过,运行成功!

nodejs调用libnotifi效果图

回到上面,libnotify是基于c的库,而libnotifymm是对libnotify的C++封装,怪不得linux之父linus选择C而抛弃C++,看来C++却是是一团糟糕得状态啊,能用C简单清晰地实现的话,再用C++感觉却是有点画蛇添足的感觉。

编译成node addon

wiki上给的编译命令是gcc -o hello_worldpkg-config --cflags --libs libnotifyhello_world.c。对应到Node Addon中来的重点就是需要把pkg-config'命令产生的内容显示地告知编译器。分别通过cflagslibraries字段。

查阅了chromiumnode-canvas中gyp文件的书写方式,添加cflag字段就可以了

    'conditions': [
        ['OS=="win"', {
            'libraries': [
                '-lnode.lib'
            ]
        }, {
            'cflags': [
                '<!@(pkg-config libnotify --cflags)' #for libnotify
            ],
            'libraries': [
                '<!@(pkg-config libnotify --libs)'
            ]
        }]
    ]

C++ 相关的知识

static 关键字的用途

V8 相关的知识

// Extracts a C string from a V8 Utf8Value.
const char* ToCString(const v8::String::Utf8Value& value) {
  return *value ? *value : "<string conversion failed>";
}

String::Utf8Value str(optsIcon);

icon = ToCString(str);  // 方法一

void *p = static_cast<void*>(&str); // 方法二, 乱码...不知道为啥
icon = static_cast<const char*>(p);

/**
 * 最终的解决方案
 * https://groups.google.com/forum/#!topic/nodejs/aNeC6kyZcFI
 */
// convert a v8::String to a (char*) -- any call to this should later be free'd
#include <stdlib.h> //calloc
#include <cstring> //strncpy
static inline char *TO_CHAR(Handle<Value> val) {
    String::Utf8Value utf8(val->ToString());

    int len = utf8.length() + 1;
    char *str = (char *) calloc(sizeof(char), len);
    strncpy(str, *utf8, len);

    return str;
}