使用GDBus在D-Bus上发送一个字节数组(类型`ay`)

时间:2014-04-08 12:49:42

标签: c dbus gdbus

我正在尝试使用GDBus绑定通过D-Bus进行字节数组。能告诉我如何实现这一目标吗?我试过谷歌搜索,但没有帮助。

字节数组包含图像文件,因此无法转换为charbytearray

任何帮助都是适当的

4 个答案:

答案 0 :(得分:5)

我使用XML进行了一些测试,其中我使用了类型ay。这适用于QT绑定(使用qdbusxml2cpp生成),它转换为QByteArray,但它似乎不适用于glib绑定(使用gdbus-codegen生成)它在gchar *翻译,似乎你在\0之后失去了什么 - 因为它以某种方式处理为一个字符串。但是你会发现:

  

可以使用注释org.gtk.GDBus.C.ForceGVariant关闭此自动映射 - 如果使用,则始终交换GVariant而不是相应的本机C类型。对于可能嵌入NUL字节的数据使用字节串(type-string ay)时,此注释可能很方便。

根据https://developer.gnome.org/gio/stable/gdbus-codegen.html,您可以将其作为GVariant来处理。我通过在每个arg上添加注释org.gtk.GDBus.C.ForceGVariant <annotation name="org.gtk.GDBus.C.ForceGVariant" value="true"/>的标记对此进行了测试,并且它可以正常运行。

答案 1 :(得分:3)

实际上,您可以使用&#34; a(y)&#34;而不是使用&#34; ay&#34;类型。 glib绑定将翻译&#34; a(y)&#34;到GVariant *。

然后你可以使用&#34; GVariant&#34;处理参数。

e.g。 xml文件

<method name="parsePacket">
  <arg direction="in" name="message" type="a(y)">
    <doc>
      <line>type: const Uint8 *</line>
    </doc>
  </arg>
</method>

生成方法:

gboolean (*handle_parse_packet) (
IDbusObject *object, GDBusMethodInvocation *invocation, GVariant *arg_message);

gboolean idbusobject_call_parse_packet_sync (
   IDbusObject *proxy,
   GVariant *arg_message,
   GCancellable *cancellable,
  GError **error);

您可以使用&#34; GVariant&#34;提取和插入数据。方法

在客户端插入数据:

void parsePacket (unsigned char* arg_message, guint16 arg_length)
{
    GVariantBuilder *builder;
    GVariant *value;

    builder = g_variant_builder_new (G_VARIANT_TYPE ("a(y)"));
    for (int i = 0; i < arg_length; i++)
    {
        g_variant_builder_add (builder, "(y)", arg_message[i]);
    }
    value = g_variant_new ("a(y)", builder);
    g_variant_builder_unref (builder);

    idbusobject_call_parse_packet_sync(proxy,
        value,
        NULL,
        NULL);
}

在服务器端提取数据:

gboolean handleParsePacket (
    IDbusObject *object,
    GDBusMethodInvocation *invocation,
    GVariant *arg_message)
{
    unsigned char byteArray[2048];
    int actualLength = 0;

    GVariantIter *iter;
    guchar str;

    g_variant_get (arg_message, "a(y)", &iter);
    while (g_variant_iter_loop (iter, "(y)", &str))
    {
        byteArray[actualLength++] = str;
    }
    g_variant_iter_free (iter);

    idbusobject_complete_parse_packet( object, invocation);

    return (TRUE);
}

答案 2 :(得分:0)

This question在答案中有一些好主意,包括通过writing the data to a file and passing the filenameusing a named pipe传递大量数据。写入文件并传递文件名可能是最容易实现的。

答案 3 :(得分:0)

在客户端,您可以通过调用g_variant_new_from_data()方法轻松完成:

GVariant* convertByteArrayToVariant(unsigned char* arg_message, guint16 arg_length)
{
    return g_variant_new_from_data(
        G_VARIANT_TYPE ("a(y)"),
        arg_message,
        arg_length,
        TRUE,
        NULL,
        NULL);
}

或者,如果你有一个填充GByteArray *,你可以这样做:

GVariant* convertByteArrayToVariant(GByteArray* array)
{
    return g_variant_new_from_data(
        G_VARIANT_TYPE ("a(y)"),
        array->data,
        array->len,
        TRUE,
        NULL,
        NULL);
}