Получить указатель на структуру из структуры 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
и передать базовый байтовый массив.