在GJS中编写本机消息传递主机

时间:2017-11-28 14:14:12

标签: glib chrome-native-messaging gjs

我正在尝试为GJS中的chrome / firefox扩展编写native messaging host(因为它将依赖于已经在GJS中编写的代码)但遇到了一些障碍。我使用chrome-gnome-shell作为粗略模板,因为它也使用了GLib / Gio instrospection和GApplication,但它具有python struct的优点,而我没有。

很快,本机消息传递主机通过stdin / stdout交换消息,这是一个Int32(4字节)长度,后跟一串utf-8编码的JSON。

chrome-gnome-shell使用GLib.IOChannel set_encoding('utf-8')struct来处理int32字节。我在GJS中使用该课程时遇到了麻烦,但没有struct因此Gio.UnixInputStream Gio.DataInputStream包裹在put_int32()(和输出对应物),read_int32() / { {1}}和put_string() / read_string()

显然我对我正在做的事情感到非常困惑。如果我调用Gio.DataInputStream.read_int32()它会返回一个数字369098752,所以我猜测int32没有被转换为常规数字。如果我打电话给Gio.DataInputStream.read_bytes(4, null).unref_to_array()来获得ByteArray; ByteArray.toString()返回'\ u0016',而ByteArray [0]返回'22',这似乎是实际长度。

关于将int32读取/写入数据流的一些指示,非常感谢。

chrome-gnome-shell引用:

2 个答案:

答案 0 :(得分:0)

我不知道这是否是解决这个问题的最佳方法,但这就是我想出来的。

使用ByteArray导入的两个函数(从SO上的某处修改):

const ByteArray = imports.byteArray;

function fromInt32 (byteArray) {
    var value = 0;

    for (var i = byteArray.length - 1; i >= 0; i--) {
        value = (value * 256) + byteArray[i];
    }

    return value;
};

function toInt32 (num) {
    var byteArray = [0, 0, 0, 0];

    for (var index_ = 0; index_ < byteArray.length; index_++) {
        var byte = num & 0xff;
        byteArray [index_] = byte;
        num = (num - byte) / 256 ;
    }

    return ByteArray.fromArray(byteArray);
};

接收/发送:

const Gio = imports.gi.Gio;

// Receiving
let stdin = new Gio.DataInputStream({
    base_stream: new Gio.UnixInputStream({ fd: 0 })
});

let int32 = stdin.read_bytes(4, null).toArray();
let length = fromInt32(int32);
let data = stdin.read_bytes(length, null).toArray().toString();
let message = JSON.parse(data);

// Sending
let stdout = new Gio.DataOutputStream({
    base_stream: new Gio.UnixOutputStream({ fd: 1 })
});

let data = JSON.stringify(message);
let int32 = toInt32(data.length);
stdout.write(int32, null);
stdout.put_string(data, null);

当然,您应该将这些包装在try-catch中,并且您可能希望将源连接到输入(您可以使用Gio.UnixInputStream):

let source = stdin.base_stream.create_source(null);
source.set_callback(onReceiveFunc);
source.attach(null);

答案 1 :(得分:0)

您可以像使用read_bytes()put_string()一样使用Gio.DataOutputStream.put_int32()Gio.DataInputStream.read_int32()