【问题标题】:Writing a native messaging host in GJS在 GJS 中编写本机消息传递主机
【发布时间】:2017-11-28 14:14:11
【问题描述】:

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

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

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

显然,我对自己在做什么感到非常困惑。如果我打电话给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 参考:

【问题讨论】:

    标签: glib chrome-native-messaging gjs


    【解决方案1】:

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

    使用 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);
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 我确实尝试过使用read_int32()put_int32(),但它们似乎并没有转换为标准的base-10 javascript Number,而是返回一个巨大的数字。这可能是 GJS/GIR 错误吗?
      • 是的,听起来像一个错误。错误跟踪器现在位于 gitlab.gnome.org/GNOME/gjs
      • 整洁,代码高亮和其他东西 ;) 错误报告:gitlab.gnome.org/GNOME/gjs/issues/20
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多