问题
I am trying to a byte array over D-Bus using the GDBus bindings. Can you please let me know how I can achive that. I tried googling but didnt help.
Byte array contains a image file so cannot be converted to charbytearray
Any help is appriciated
回答1:
This question has some good ideas in the answers including for passing large amounts of data by writing the data to a file and passing the filename, or using a named pipe. Writing to a file and passing the file name might be the easiest to implement.
回答2:
I did some tests using an XML where I used the type ay
. This works well with the QT binding (generated with qdbusxml2cpp
) where it translates into QByteArray
however it seems that it doesn't work with the glib binding (generated with gdbus-codegen
) where it translates in gchar *
and it seems you lose what's after \0
- because somehow it's handled as a string. However you will find that:
This automatic mapping can be turned off by using the annotation org.gtk.GDBus.C.ForceGVariant - if used then a
GVariant
is always exchanged instead of the corresponding native C type. This annotation may be convenient to use when using bytestrings (type-stringay
) for data that could have embedded NUL bytes.
Which means according to https://developer.gnome.org/gio/stable/gdbus-codegen.html that you could handle it as GVariant
. I tested this by adding the tag for annotation org.gtk.GDBus.C.ForceGVariant
<annotation name="org.gtk.GDBus.C.ForceGVariant" value="true"/>
on each arg and it works.
回答3:
Actually, instead of using type "ay", you can use "a(y)". The glib binding would translate "a(y)" to GVariant*.
And then you can use "GVariant" handling to deal with the parameter.
e.g. the xml file
<method name="parsePacket">
<arg direction="in" name="message" type="a(y)">
<doc>
<line>type: const Uint8 *</line>
</doc>
</arg>
</method>
Generated 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);
You can extract and insert data using "GVariant" method.
Insert data at client side:
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);
}
Extract data at server side:
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);
}
回答4:
At the client side, you could do it easier by calling the g_variant_new_from_data() method:
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);
}
Or, if you have a populated a GByteArray*, you could do it like this:
GVariant* convertByteArrayToVariant(GByteArray* array)
{
return g_variant_new_from_data(
G_VARIANT_TYPE ("a(y)"),
array->data,
array->len,
TRUE,
NULL,
NULL);
}
来源:https://stackoverflow.com/questions/22937588/sending-a-byte-array-type-ay-over-d-bus-using-gdbus