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



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

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

Chrome-gnome-shell 使用带有set_encoding('utf-8')structGLib.IOChannel来处理 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 到数据流的指针,将不胜感激。

铬侏儒外壳参考:

  • on_input()
  • send_message()

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

使用字节数组导入的两个函数(从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);

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

最新更新