1

我正在尝试为 GJS 中的 chrome/firefox 扩展编写本机消息传递主机(因为它将依赖已经用 GJS 编写的代码),但遇到了一些障碍。我使用chrome-gnome-shell作为粗略模板,因为它还使用 GLib/Gio 自省和 GApplication,但它具有struct我没有的 python 优势。

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

chrome-gnome-shell 使用GLib.IOChannelwithset_encoding('utf-8')struct来处理 int32 字节。我在 GJS 中使用该类时遇到了麻烦,并且没有struct尝试使用/和/Gio.UnixInputStream包裹Gio.DataInputStream(和输出对应物)。put_int32()read_int32()put_string()read_string()

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

一些关于读取/写入 int32 到数据流的指针,将不胜感激。

chrome-gnome-shell 参考:

4

2 回答 2

0

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

于 2017-12-04T00:25:51.993 回答
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);
于 2017-11-29T16:25:17.363 回答