Получить указатель на структуру из структуры Dart_NativeArguments в C

Я пытаюсь обернуть библиотеку C, используя Dart. Я вызываю функцию C из dart и передаю аргументы через структуру Dart_NativeArguments в C:

    void _sayHello(Dart_NativeArguments arguments) {
    string from;
    Dart_Handle seed_object = HandleError(Dart_GetNativeArgument(arguments, 0));
    if (Dart_IsString(seed_object)) {
        const char* seed;
        HandleError(Dart_StringToCString(seed_object, &seed));
        from = seed;
    }
    num = (int)Dart_GetNativeArgument(arguments, 1);

    Dart_SetReturnValue(arguments, HandleError(Dart_NewStringFromCString(sayHello(from, num).c_str())));
}

В Dart я вызываю функцию и передаю необходимые аргументы

String sayHello(String from) native "sayHello";

main() {
  print(sayHello("Dart"));
}

Мне было интересно, как я мог бы передать указатели (на структуру, которую я сделал) вместо просто строк и целых в качестве аргументов. В Dart есть функции для преобразования Dart_Handles в строки и целые, но не в указатели. Какова внутренняя структура Dart_Handle и как мне преобразовать его обратно в указатель? Например:

Код дротика:

String sayHello(info from) native "sayHello";


class info
{
  String message;
  int num;
}

main() {
  info tester = new info();
  tester.message = "Dart";
  tester.num = 2;
  print(sayHello(tester));
}

Код C:

void sayHello(Dart_NativeArguments arguments) {
    /*What do I do here to get back a pointe to the struct/class I passed
      in as an argument in Dart?*/
}

1 ответ

Решение

Ваш Dart_NativeArguments будет состоять только из одного элемента, который будет экземпляром - экземпляром класса info что вы создали с new info(), Вы можете проверить, является ли это экземпляром с bool Dart_IsInstance(Dart_Handle object), Итак, у вас есть дескриптор экземпляра информации. Это позволяет вам получить доступ к его полям экземпляра (сообщение и номер), чтобы получить и установить их, используя Dart_GetField а также Dart_SetField,

Dart_Handle instance = Dart_GetNativeArgument(arguments, 0);
Dart_Handle message_handle = Dart_GetField(retobj, NewString("message"));
char* message;
Dart_StringToCString(message_handle, &message);
Dart_Handle number_handle = Dart_GetField(retobj, NewString("num"));
int64_t number;
Dart_IntegerToInt64(number_handle, &number);
// message contains the string, number contains the number
// use them, copy them etc

Я знаю, что это только пример, но может быть проще переопределить sayHello принимать 2 аргумента (строку и целое число) вместо передачи экземпляра объекта. Нет доступа к полям класса за один шаг, вам нужно обращаться к ним индивидуально. Рассмотрим две версии кода Dart: одну передают экземпляр объекта, а другую только значения. Вторая версия проще на стороне Dart и C (без шагов GetField). Однако первая версия более мощная, потому что вы можете обновить поля, используя SetField, чего нельзя было сделать во второй.

class Info {
  String message;
  int num;

  Info(this.message, this.num);
}

version1() {
  sayHelloV1(new Info('Dart', 2));
}

version2() {
  sayHelloV2('Dart', 2);
}

Если ваш C API требует от вас передать struct Вы должны будете создать это в своем коде C, скопировав значения, которые вы извлекаете, используя Dart_IntegerToInt64и т.д. в него, затем передайте указатель на вашу структуру C в API.

Если ваш API очень точен в отношении упаковки / заполнения данных в структуру, вы можете использовать Dart typed_data упаковать типы дротиков в ByteData и передать базовый байтовый массив.

Другие вопросы по тегам