使用camlidl与不透明结构进行接口

时间:2018-10-04 22:26:48

标签: ocaml

我正在尝试将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);

这将为ml_c和c2ml帮助器生成一个带有“虚拟” #define设置的_stubs.c,如下所示:

...
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这样做似乎是一种粗略的方法!我可能会提交一个pull req来添加一个特殊情况参数,这样,如果您将其标记为 void (例如c2ml(void)),它将完全省略创建c2ml或ml2c函数的操作。它似乎仍然像黑客一样,应该有一种更好的支持方式。有想法吗?

1 个答案:

答案 0 :(得分:0)

我最终确实通过电子邮件向Xavier Leroy(项目维护者)发送了电子邮件,这是他的回复。

  

我会尽力帮助您,但作为回复的序言:

     

camlidl是我在1990年代后期开发的一个旧项目,   从那时起,除了确保它仍然   使用最新的OCaml版本进行编译。一些项目仍在使用   camlidl,尤其是在Microsoft,但最近的项目往往会   请改用Ctypes(https://github.com/ocamllabs/ocaml-ctypes)。一世   不建议您将camlidl用于新项目。

     

现在回答您的问题:以下方法应该起作用

quote(C, "#include <lib.h>")
quote(C, "void t_final (t * x) { destroy_opaque_struct (*x); }")

typedef [abstract,finalize(t_final)] struct opaque_struct * t;
     

假设lib.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 *);
     

令人困惑的是typedef opaque_struct * t被拒绝了   因为CamlIDL不知道类型opaque_struct。但是   未知结构没有问题...