Отправка байтового массива (тип `ay`) по D-Bus с использованием GDBus

Я пытаюсь массив байтов по D-Bus, используя привязки GDBus. Пожалуйста, дайте мне знать, как я могу этого достичь. Я пытался гуглить, но не помогло.

Байт массив содержит файл изображения, поэтому не может быть преобразован в charbytearray

Любая помощь оценивается

4 ответа

Решение

У этого вопроса есть несколько хороших идей в ответах, включая передачу больших объемов данных путем записи данных в файл и передачи имени файла или использования именованного канала. Запись в файл и передача имени файла может быть проще всего реализовать.

Я сделал несколько тестов, используя XML, где я использовал тип ay, Это хорошо работает с привязкой QT (генерируется с qdbusxml2cpp) где это переводится на QByteArray однако кажется, что он не работает с привязкой glib (генерируется с gdbus-codegen) где это переводится в gchar * и кажется, что ты теряешь то, что после \0 - потому что так или иначе это обрабатывается как строка. Однако вы найдете, что:

Это автоматическое сопоставление можно отключить с помощью аннотации org.gtk.GDBus.C.ForceGVariant - если используется, то GVariant всегда заменяется вместо соответствующего собственного типа C. Эту аннотацию может быть удобно использовать при использовании строк байтов (строка типа ay) для данных, которые могут иметь встроенные байты NUL.

Что означает в соответствии с https://developer.gnome.org/gio/stable/gdbus-codegen.html что вы можете справиться с этим как GVariant, Я проверил это, добавив тег для аннотации org.gtk.GDBus.C.ForceGVariant<annotation name="org.gtk.GDBus.C.ForceGVariant" value="true"/> на каждом арге и все работает.

На самом деле, вместо использования типа "ay", вы можете использовать "a(y)". Привязка glib переводит "a (y)" в GVariant*.

И тогда вы можете использовать обработку "GVariant" для работы с параметром.

например, 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);

Вы можете извлекать и вставлять данные, используя метод "GVariant".

Вставьте данные на стороне клиента:

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);
}

На стороне клиента вы могли бы сделать это проще, вызвав метод 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);
}
Другие вопросы по тегам