Lisp 通过SBCL FFI传递和接收字符串

Lisp 通过SBCL FFI传递和接收字符串,lisp,common-lisp,Lisp,Common Lisp,我有一个用优化c编写的复杂库(library.c): 该图书馆汇编如下: gcc library.c -o library.so -shared 我正试图从SBCL中利用它,以下是我的最后一个想法(我放弃并转向stackoverflow): 在运行时,例如,(打印名称版本“Program”1),我得到 lib-name: Program lib-fullname: Program-1 dummy-string NIL 因此,除了将字符串传递回lisp之外,其他一切都可以工作。这个例子有什么不

我有一个用优化c编写的复杂库(library.c):

该图书馆汇编如下:

gcc library.c -o library.so -shared
我正试图从SBCL中利用它,以下是我的最后一个想法(我放弃并转向stackoverflow):

在运行时,例如,(打印名称版本“Program”1),我得到

lib-name: Program
lib-fullname: Program-1
dummy-string
NIL
因此,除了将字符串传递回lisp之外,其他一切都可以工作。这个例子有什么不对劲?谢谢你,安德烈

更新我已经让我的lisp代码正常工作了,但我仍然不明白为什么原始代码段失败了。这是一个有效的:

(defun print-name-version (name version)
  (let ((fullname (make-alien char 100)))
    (make_fullname fullname name version)
    (with-alien ((fn-str-repr (c-string :external-format :ascii) fullname))
      (format t "~a~%" fn-str-repr))
    (free-alien fullname)))

我从未使用过SBCL本地FFI绑定,但我想我已经找到了答案。作为将来的参考,您更有可能获得有关特定于实现的FFI绑定的帮助,而不是帮助

从Lisp代码访问时,外来类型c-string的变量会自动转换为Lisp字符串。顶级函数
make_fullname
是Lisp代码,它依次调用外来例程,但此时
fullname
已被转换为Lisp字符串,然后被转换为新的c字符串,一旦调用完成就会丢弃


您需要执行编辑中所做的操作:分配存储缓冲区并将其传递给alien函数,并将关联的c字符串变量视为该存储上的Lisp视图。

感谢您解决了这个难题(并且提到了CFFI,我是Lisp新手,这是我第一次看到该链接:)请注意:如果make_fullname的调用者没有为格式化字符串提供足够的存储空间,您可能需要记住,这里可能存在缓冲区溢出。我还认为这段代码只是为了做个例子,不是你的“复杂库”吗?因为在后一种情况下,您知道您可以执行
(defun make version(name version)(格式为nil“~a-~d”name version))
,对吗?:)当然,这些只是一些熟悉外国金融机构的尝试。
(load-shared-object "library.so")

(define-alien-routine make_fullname void
  (fullname (c-string :external-format :ascii))
  (name (c-string :external-format :ascii))
  (x int))


(defun print-name-version (name version)
  (with-alien ((fullname (c-string :external-format :ascii)))
    (setf fullname (make-alien char 100))
    (setf fullname "dummy-string")
    (make_fullname fullname name version)
    (format t "~a~%" fullname)))
lib-name: Program
lib-fullname: Program-1
dummy-string
NIL
(defun print-name-version (name version)
  (let ((fullname (make-alien char 100)))
    (make_fullname fullname name version)
    (with-alien ((fn-str-repr (c-string :external-format :ascii) fullname))
      (format t "~a~%" fn-str-repr))
    (free-alien fullname)))