我想为 C 库(SOIL)生成一个通用的 lisp cffi 包装器,虽然我对 cl 和 cffi 很有信心,但我不确定要使用哪些库或如何开始使用它们。基本上我会问一个更详细的问题,但不知道我不知道什么。
1 回答
[更新] 这已经过时了。这些天我建议研究cl-autowrap或cffi/c2ffi
那里有一些包装器生成器,但有两个名称从该组中脱颖而出,SWIG 和 Verrazano。
Verrazano 现在没有维护,所以真的不应该依赖,但是对于你使用 SOIL 库,它可以工作......有点!以下步骤直接取自使用 kinect 和 common lisp的示例。
首先,确保您已安装 gcxml。对我来说,这是按如下方式完成的:
sudo apt-get install gccxml
现在在您的 repl 中(您可能必须根据您的系统编辑路径):
(ql:quickload :cffi)
(ql:quickload :verrazano)
(verrazano:generate-binding (list :cffi :package-name :soil :input-files (list "SOIL/SOIL.h")))
您现在在 soil.lisp 文件中有一个包装器。我马上就发现了问题,枚举的命名非常奇怪(.-1 .-2 等),并且这些相同的奇怪名称正在被导出。我删除了这些并重命名了枚举。然后您会发现函数调用中没有使用枚举,因此您需要修改“defcfun”调用以使用它们。
如果您不习惯这样做,我建议您找到一个已经完成此操作的库作为指南。我发现 lispbuilder 在这方面有一些广泛的例子。
SWIG 绝对是更好的选择,即使使用复杂的库也能很好地为您服务。一般的做法是编写一个 SWIG 接口文件,它告诉 swig 在哪里可以找到库以及要包装哪些功能。SWIG 的文档非常广泛且非常好:
http://www.swig.org/Doc2.0/Contents.html#Contents
还可以查看他们关于 Swig 和 Common Lisp 的页面http://www.swig.org/Doc2.0/Lisp.html
现在最好使用单独的接口文件,原因如下(取自 swig 文档)
- 很少需要访问大包中的每个函数。许多 C 函数在脚本环境中可能很少或根本没有用处。因此,为什么要包装它们?
- 单独的接口文件提供了提供有关如何构造接口的更精确规则的机会。
- 接口文件可以提供更多的结构和组织。
- SWIG 无法解析出现在头文件中的某些定义。拥有一个单独的文件可以让您消除或解决这些问题。
- 接口文件对接口是什么提供了更精确的定义。想要扩展系统的用户可以转到接口文件并立即查看可用的内容,而无需从头文件中挖掘出来。
...但是,您通常可以不写任何内容就离开,让 SWIG 解决。对于土壤,这涉及以下内容:
编写一个名为 soil.i 的文件并将以下内容放入其中(您可能需要更改路径)。
%module soil
%{
/* Includes the header in the wrapper code */
#include "/usr/include/SOIL/SOIL.h"
%}
/* Parse the header file to generate wrappers */
%include "/usr/include/SOIL/SOIL.h"
接下来在终端 swig -cffi -module soil soil.i 运行以下命令
您将拥有一个新的 soil.lisp 文件。与 verrazano 一样,请查看函数调用以查看枚举是如何使用的(或者更有可能不使用)。
现在有了这两个,你几乎肯定想让事情变得更“口齿不清”。通常有一些指针传递给要由 C 函数填充的函数,您希望对用户隐藏这些指针。
这是一个开始的地方,希望你可以从这里开始工作。再见