Я пытаюсь использовать camlidl
с библиотекой C для генерации привязок OCaml.Эта библиотека использует метод «непрозрачной структуры» для сохранения состояния объекта: все функции берут или дают указатель на структуру, что означает, что мой код не имеет никакой видимости в ней.Файл библиотеки .h содержит что-то вроде:
typedef struct opaque_struct opaque_struct;
opaque_struct * create_opaque_struct;
int do_x_with_opaque_struct(int, opaque struct *);
void destroy_opaque_struct(opaque struct *);
, и поэтому я, как ожидается, никогда не буду использовать структуру напрямую, а вместо этого буду использовать указатель на нее везде.
К сожалению, я не могуВы не найдете в руководстве camlidl
, как это сделать правильно.Я проверил следующие разделы:
3.5 Структуры
Ничто из этого не полезно для меня - я имею дело с неполным определением структуры и не хочу / не могу / не могуиспользуйте любой перевод к объекту caml.
3.2 Указатели
Кажется, это должно работать, чтобы всегда использовать [ptr] struct opaque_struct *
везде.Но у этого есть недостаток: destroy_opaque_struct(opaque_struct * x)
не вызывается автоматически, когда объект выходит из области видимости и происходит GC.Это вынуждает пользователя OCaml самостоятельно управлять ссылками.
3.8 Определения типов
Хотя это даст мне [finalize(destroy_opaque_struct)]
, как я хотел для GC, я не могу использовать typedef, так как генерирует неработающий код .Я пробовал typedef [abstract] struct opaque_struct opaque_struct
один.Это генерирует подпрограммы c2ml и ml2c, которые не работают: они пытаются выполнить присваивание указателя для неполного типа, который не работает вообще.
Так, каков правильный способ справиться с этим?Это похоже на достаточно распространенный сценарий использования, и я думаю, что camlidl должен его поддерживать, но я что-то упустил.
РЕДАКТИРОВАТЬ: Некоторые играют, и я нашел один способ сделать это.Рассмотрим test.idl, содержащий:
quote(c, "void camlidl_destroy_opaque_struct(opaque_struct * x) { destroy_opaque_struct(x); }");
typedef [abstract,finalize(camlidl_destroy_opaque_struct),ml2c(dummy),c2ml(dummy)] struct opaque_struct opaque_struct;
[ptr] * opaque_struct create_opaque_struct();
int do_x_with_opaque_struct([in] int int_param, [in,ptr] opaque_struct * struct_param);
Это создает файл _stubs.c с "пустышкой" #define для помощников ml2c и c2ml, например:
...
void camlidl_destroy_opaque_struct(opaque_struct * x) {
destroy_opaque_struct(x); }
#define camlidl_ml2c_test_opaque_struct(v,c,ctx) dummy(v,c)
#define camlidl_c2ml_test_opaque_struct(c,ctx) dummy(c)
value camlidl_test_create_opaque_struct(value _unit)
{
...
Поскольку я никогдана самом деле используйте opaque_struct напрямую, c2ml и ml2c фактически никогда не вызываются, поэтому нормально, что их нет.
Тем не менее, MAN кажется, что это грубый способ сделать это!Я могу отправить запрос тяги, чтобы добавить параметр специального случая, чтобы, если вы пометите его void (например, c2ml(void)
), он полностью пропустил создание функции c2ml или ml2c.Это все еще похоже на взлом, и должен быть способ с лучшей поддержкой.Мысли?