如何在clisp中使用FFI:def-call-in

How to use FFI:def-call-in in clisp

我已经弄清楚如何使用 FFI:def-call-out 将 C 代码创建的共享对象用于 Clisp,但我无法弄清楚如何使用 FFI:Def-call-in

我不知道这个过程,实际上我很困惑,如果 clisp 也会创建一些 C 函数可以使用的 .so 文件或其他东西。

有人可以解释一个编写此类回调函数的最小工作示例吗?

Example 32.7. Calling Lisp from C:

要使用 Lisp 函数 SORT 而不是 C 库函数 qsort 对双浮点数数组进行排序,可以使用以下接口代码 sort1.c。主要问题是传递一个可变大小的数组。

extern void lispsort_begin (int);
void* lispsort_function;
void lispsort_double (int n, double * array) {
  double * sorted_array;
  int i;
  lispsort_begin(n); /* store #'sort2 in lispsort_function */
  sorted_array = ((double * (*) (double *)) lispsort_function) (array);
  for (i = 0; i < n; i++) array[i] = sorted_array[i];
  free(sorted_array);
}

这伴随着sort2.lisp:

(DEFPACKAGE "FFI-TEST" (:use “COMMON-LISP” “FFI”))
(IN-PACKAGE "FFI-TEST")
(EVAL-WHEN (compile) (setq FFI:*OUTPUT-C-FUNCTIONS* t))
(FFI:DEF-CALL-IN lispsort_begin (:ARGUMENTS (n int))
  (:RETURN-TYPE nil)
  (:LANGUAGE :stdc))
(FFI:DEF-C-VAR lispsort_function (:type c-pointer))
(defun lispsort_begin (n)
  (setf (cast lispsort_function
              `(c-function
                 (:ARGUMENTS (v (c-ptr (c-array double-float ,n))))
                 (:RETURN-TYPE (c-ptr (c-array double-float ,n))
                               :malloc-free)))
        #'sort2))
(defun sort2 (v)
  (declare (type vector v))
  (sort v #'<))

要对此进行测试,请使用以下测试文件 sorttest.lisp

(EVAL-WHEN (compile) (setq FFI:*OUTPUT-C-FUNCTIONS* t))
(FFI:DEF-CALL-OUT sort10
  (:name "lispsort_double")
  (:LANGUAGE :stdc)
  (:ARGUMENTS (n int)
              (array (c-ptr (c-array double-float 10)) :in-out)))

现在试试

$ clisp-link create sort sort2.c sorttest.c
$ cc -O -c sort1.c
$ cd sort
$ ln -s ../sort1.o sort1.o

sort1.o 添加到 NEW_LIBS 并在 link.sh 中添加 NEW_FILES。创建一个包含表单

的文件 package.lisp
(MAKE-PACKAGE "FFI-TEST" :use '(“COMMON-LISP” “FFI”))

并在 link.sh 中将 package.lisp 添加到 TO_PRELOAD。进行:

$ cd ..
$ base/lisp.run -M base/lispinit.mem -c sort2.lisp sorttest.lisp
$ clisp-link add base base+sort sort
$ base+sort/lisp.run -M base+sort/lispinit.mem -i sort2 sorttest
> (sort10 10 '#(0.501d0 0.528d0 0.615d0 0.550d0 0.711d0
                0.523d0 0.585d0 0.670d0 0.271d0 0.063d0))
#(0.063d0 0.271d0 0.501d0 0.523d0 0.528d0 0.55d0 0.585d0 0.615d0 0.67d0 0.711d0)
$ rm -r base+sort