CL和SWIG:工作实例?

Rob*_*n B 6 swig sbcl common-lisp

做一个SWIG教程,并使用example.c,example.i,因为他们在那里提供.我生成了lisp文件swig -cffi example.i.

但是,当我test.lisp与SBCL一起运行时,我会收到关于未定义外来函数的投诉,以及编译example.lisp自身时的投诉.我很确定我仍然需要将我的example.c编译成一个库然后以某种方式告诉SBCL加载它!但该文档是在这个非常稀少,除了这个.

有人可以告诉我如何做到这一点,还是有一种比SWIG更好的方法从C/C++源自动生成CFFI绑定?

sbcl输出:

...
; 
; caught STYLE-WARNING:
;   Undefined alien: "fact"
; 
; compilation unit finished
;   caught 1 STYLE-WARNING condition
; 
; caught STYLE-WARNING:
;   Undefined alien: "my_mod"
...
Run Code Online (Sandbox Code Playgroud)

test.lisp

;call C functions defined in example.c

(require :cffi)
;;;(require :example "example.lisp")
(load "example.lisp")
(fact 2)
(quit)
Run Code Online (Sandbox Code Playgroud)

svk*_*svk 8

首先,您需要编译C库.做类似的事情:

gcc -shared example.c -o libexample.so
Run Code Online (Sandbox Code Playgroud)

当然,对于复杂的现有库,编译可能要复杂得多 - 如果要包装现有库,它可能会附带某种Makefile来帮助您构建它.

然后,在Lisp中,使用CFFI来定义和加载库.这似乎是你缺少的主要部分.

(cffi:define-foreign-library libexample
    (t (:default "libexample"))) ;; note no .so suffix here
(cffi:use-foreign-library libexample)
Run Code Online (Sandbox Code Playgroud)

这部分:

(t (:default "libexample"))
Run Code Online (Sandbox Code Playgroud)

是一个条件,您可以使用它为不同的平台提供不同的加载指令.(t ...)是catchall选项,就像COND一样.您可以在define-foreign-library的文档中找到确切的语法.

您现在通常使用cffi:defcfun等来定义库中的函数.这是SWIG生成的文件为您所做的,所以加载它:

(load "example.lisp")
Run Code Online (Sandbox Code Playgroud)

您现在可以将函数称为普通的Lisp函数:

(fact 5)
  => 120
Run Code Online (Sandbox Code Playgroud)