c - 使用 CFFI 从 Common Lisp 向堆栈上的 C 函数传递和返回结构

标签 c common-lisp cffi

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

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

CFFI 的当前版本支持通过 libffi 在堆栈上传递和返回结构,如 this question 中所述。然而,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 返回结构将占用多少内存,然后手动“解析”它?

最佳答案

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

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

但是对于 Chipmunk,该技术在 Windows/Linux 上使用 SBCL、CCL、ECL 时效果很好。但是,Chipmunk 结构有两个 float 成员,所以它非常基础。

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

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

长话短说:

  1. 也许,试试吧。
  2. 没有。期待段错误。有时通过电子邮件向 C 库的维护者发送电子邮件并礼貌地询问会得到指示而不是值 =]。

关于c - 使用 CFFI 从 Common Lisp 向堆栈上的 C 函数传递和返回结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23579340/

相关文章:

C 正确使用 free

function - LISP 编写一个名为 cut-in-half 的函数,它接收一个列表并创建一个新列表,其元素是前半部分和后半部分

loops - 在宏上使用循环在 Common Lisp 中生成类槽

macros - 从 CL 宏中的字符串创建类访问器名称

python - Linux 上的 cffi 包安装错误

python - CFFI 在 Python (Linux) 虚拟环境中失败——试图在 venv 中安装加密包

lisp - 如何获取 Lisp 进程中可用的所有环境变量的列表?

c - 在 Bison 中解析一个 While 循环

c - 接收 SIGTERM

C语言-查找包含字母的单词