使用 SBCL FFI 传递和接收字符串
我有一个用优化的c(library.c)编写的复杂库:
#include <stdio.h>
#include "library.h"
void make_fullname(char* fullname, char* name, int version) {
sprintf(fullname, "%s-%d", name, version);
printf("lib-name: %s\n", name);
printf("lib-fullname: %s\n", fullname);
}
其中library.h包含
void make_fullname(char* fullname, char* name, int version);
该库编译如下:
gcc library.c -o library.so -shared
我试图从SBCL中使用它,这是我的最终结果(我给出的那个)并转到 stackoverflow):
(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)))
运行时,例如,(print-name-version "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)))
I have a sophisticated library written in optimized c (library.c):
#include <stdio.h>
#include "library.h"
void make_fullname(char* fullname, char* name, int version) {
sprintf(fullname, "%s-%d", name, version);
printf("lib-name: %s\n", name);
printf("lib-fullname: %s\n", fullname);
}
where library.h contains
void make_fullname(char* fullname, char* name, int version);
The library is compiled as follows:
gcc library.c -o library.so -shared
I am trying to make use of it from SBCL, here is my final take (the one on which I give up and turn to stackoverflow):
(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)))
Upon running, e.g., (print-name-version "Program" 1) I get this
lib-name: Program
lib-fullname: Program-1
dummy-string
NIL
So, everything works except for passing the string back into lisp. What is amiss in this example? Thanks, Andrei.
Update I have got my lisp code to work, but I still don't really get why the original snippet fails. Here is a working one:
(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)))
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我从未使用过 SBCL 原生 FFI 绑定,但我想我已经弄清楚了。为了将来参考,您更有可能获得有关 CFFI 的帮助,而不是实现特定的 FFI 绑定。
当从 Lisp 代码访问时,外来类型 c 字符串的变量会自动转换为 Lisp 字符串。顶层函数
make_fullname
是 Lisp 代码,它依次调用外星人例程,但此时fullname
已转换为 Lisp 字符串,然后再转换为new c 字符串,调用完成后将被丢弃。您需要执行编辑中所做的操作:分配存储缓冲区并将其传递给 Alien 函数,并将关联的 C 字符串变量视为该存储上的 Lisp 视图。
I have never used SBCL native FFI bindings, but I think I figured it out. For future reference, you would be more likely to get help about CFFI rather than implementation specific FFI bindings.
Variables of alien type c-string are automatically converted to Lisp strings when accessed from Lisp code. The top level function
make_fullname
is Lisp code, which in turns calls the alien routine, but by that timefullname
has been converted to a Lisp string, which then gets converted to a new c-string, which is discarded once the call finishes.You need to do what you did in the edit: allocate storage buffer and pass that to the alien function, and treat the associated c-string variable as a Lisp view on that storage.