通过使用CFFI的Common Lisp将结构传递给C函数并将其返回到堆栈

时间:2014-05-10 09:25:36

标签: c common-lisp cffi

这是问题Common lisp, CFFI, and instantiating c structs的后续问题,所以基本上这个问题是关于从带有CFFI的Common Lisp传递和返回堆栈上的c函数的c-structs。

上述问题(自2010年起)的答案是,这是不可能的。

当前版本的CFFI支持通过libffi在堆栈上传递和返回结构,如this question中所述。但是,libffi引入了另一个依赖项,而libffi在我所针对的所有系统上进行编译并不容易。因此我不想使用libffi,因为我只有很少的这样的函数可以调用。

正如我所链接的第一个问题所讨论的,可以通过解构结构来调用期望堆栈上的struct参数的c函数。例如,这是一个结构和一个函数定义:

typedef struct
{
    int width;        
    int height;       
    bool isGreat; 
} mystruct;

int do_something(mystruct rect);

可以使用

从Common Lisp调用此函数
(cffi:defcfun ("do_something" do-something)
    :int
  (width :int)
  (height :int)
  (is-great :boolean))

现在,我有两个问题:

  1. 这肯定适用于所有平台吗?我认为在C语言中,根据定义,在这种情况下结构的布局与各个参数完全一致,因此保证可行,但我不确定。

  2. 返回结构怎么样?假设有一个C函数

    mystruct foo();
    

    是否有可能以不同方式从Common Lisp调用此方法,而不使用libffi,例如:通过告诉CFFI返回结构将占用多少内存,然后解析"手动吗?

1 个答案:

答案 0 :(得分:0)

您在此处链接的问题的原始提问者。

我尝试过结构解构技术并取得了不同程度的成功。它似乎在Windows / Linux x86上工作正常,但是我尝试了一些不想合作的库(例如,当它花费/返回地址的结构时,我试图在CFFI中包装libuv)。很多段错误。

然而对于Chipmunk来说,该技术在Windows / Linux上运行良好,具有SBCL,CCL,ECL。但是,Chipmunk结构有两个浮动成员,所以它非常基本。

我总的来说,你的结构越复杂,你要求的麻烦就越多。此外,不确定这将如何移植到非x86平台。

您最好的选择是编写绑定,在您定位的每个平台上尝试它们,看看有什么中断。如果你有时间,另一个选择是编写自己的可移植C包装器,为你处理堆/堆栈的东西。我不喜欢这样,因为它是我的图书馆和用户之间的又一步,但到目前为止(除了花栗鼠和旧版本的libuv),我有幸与C合作需要指针的库。

TL; DR:

  1. 也许,试试吧。
  2. 否。期待段错误。有时通过电子邮件发送给C库的维护者并且很好地询问是否可以获得指针而不是值=]。