3

这是对Common lisp, CFFI, and instantiating c structs问题的跟进,所以基本上这个问题是关于使用 CFFI 从 Common Lisp 向堆栈上的 c 函数传递和返回 c 结构。

上面链接的问题的答案(从 2010 年开始)是不可能的。

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

正如我链接到的第一个问题中所讨论的,可以通过解构结构来调用期望堆栈上的结构参数的 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();
    

    是否有可能在不使用 libffi 的情况下从 Common Lisp 以某种方式调用它,例如通过告诉 CFFI 返回结构将占用多少内存,然后手动“解析”它?

4

1 回答 1

0

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

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

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

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

你最好的办法是编写你的绑定,在你定位的每个平台上尝试它们,然后看看有什么问题。如果您有时间,另一种选择是编写自己的可移植 C 包装器来为您处理堆/堆栈的东西。不过我不喜欢这样,因为它是我的库和它的用户之间的又一步,但到目前为止(除了花栗鼠和旧版本的 libuv)我很高兴使用需要指针的 C 库。

TL;博士:

  1. 也许,试试吧。
  2. 不。预计会有段错误。有时给 C 库的维护者发电子邮件并很好地询问会得到指针而不是值,尽管 =]。
于 2014-05-12T23:37:30.477 回答