在 GJS 中编写本地消息传递主机
Writing a native messaging host in GJS
我正在尝试编写一个 native messaging host for a chrome/firefox extension in GJS (since it will rely on code already written in GJS) but encountering some hurdles. I'm using chrome-gnome-shell 作为粗略模板,因为它也使用 GLib/Gio 自省和 GApplication,但它具有 python struct
的优点我没有。
很快,本地消息传递主机通过 stdin/stdout 交换消息,消息是一个 Int32(4 字节)长度后跟一个 utf-8 编码的字符串 JSON.
chrome-gnome-shell 使用 GLib.IOChannel
与 set_encoding('utf-8')
和 struct
来处理 int32 字节。我在 GJS 中使用 class 时遇到了问题并且没有 struct
所以一直在尝试 Gio.UnixInputStream
包装在 Gio.DataInputStream
(和输出对应物)中, put_int32()
/read_int32()
和 put_string()
/read_string()
.
显然我对自己在做什么感到非常困惑。如果我调用 Gio.DataInputStream.read_int32()
它 returns 一个数字 369098752
,那么我猜 int32 没有被转换为常规数字。如果我调用 Gio.DataInputStream.read_bytes(4, null).unref_to_array()
来获取 ByteArray; ByteArray.toString()
returns '\u0016' 而 ByteArray[0] returns '22' 似乎是实际长度。
关于 reading/writing int32 的一些指向数据流的指针,将不胜感激。
chrome-gnome-shell 参考资料:
我不知道这是否是解决此问题的最佳方法,但这是我想出的方法。
使用 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);
};
对于receiving/sending:
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()
and Gio.DataInputStream.read_int32()
。
我正在尝试编写一个 native messaging host for a chrome/firefox extension in GJS (since it will rely on code already written in GJS) but encountering some hurdles. I'm using chrome-gnome-shell 作为粗略模板,因为它也使用 GLib/Gio 自省和 GApplication,但它具有 python struct
的优点我没有。
很快,本地消息传递主机通过 stdin/stdout 交换消息,消息是一个 Int32(4 字节)长度后跟一个 utf-8 编码的字符串 JSON.
chrome-gnome-shell 使用 GLib.IOChannel
与 set_encoding('utf-8')
和 struct
来处理 int32 字节。我在 GJS 中使用 class 时遇到了问题并且没有 struct
所以一直在尝试 Gio.UnixInputStream
包装在 Gio.DataInputStream
(和输出对应物)中, put_int32()
/read_int32()
和 put_string()
/read_string()
.
显然我对自己在做什么感到非常困惑。如果我调用 Gio.DataInputStream.read_int32()
它 returns 一个数字 369098752
,那么我猜 int32 没有被转换为常规数字。如果我调用 Gio.DataInputStream.read_bytes(4, null).unref_to_array()
来获取 ByteArray; ByteArray.toString()
returns '\u0016' 而 ByteArray[0] returns '22' 似乎是实际长度。
关于 reading/writing int32 的一些指向数据流的指针,将不胜感激。
chrome-gnome-shell 参考资料:
我不知道这是否是解决此问题的最佳方法,但这是我想出的方法。
使用 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);
};
对于receiving/sending:
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()
and Gio.DataInputStream.read_int32()
。