使用 SBCL FFI 传递和接收字符串

发布于 2025-01-07 09:11:24 字数 1560 浏览 2 评论 0原文

我有一个用优化的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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

天暗了我发光 2025-01-14 09:11:24

我从未使用过 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 time fullname 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文