假设我在C中的物理库中有一个回调函数,它为附近/触摸的两个对象生成碰撞信息。这个回调需要一个(void *)数据参数,我想用它来传递我的一个lisp对象。
如何使用此(void *)参数?从我能想到的(我对CFFI相对较新,但很快掌握它)我可以
(cffi:convert-to-foreign my-obj :pointer)
,但它只返回my-obj,而不是指针,我无法用它调用回调。有关跨平台方式的任何想法吗?我知道C中的很多回调都带有void *参数,所以有人必须想到这一点。我正在使用Clozure CL,但就像我说的那样,跨平台/跨实现越多越好。谢谢!
答案 0 :(得分:3)
很抱歉,如果我的回答有点晚,但我最近遇到了同样的问题。我使用的解决方案是使用整数键将所有要通过回调访问的lisp对象存储在哈希表中。我所要做的就是将密钥传递给c函数,如果需要,将其转换为void *。
答案 1 :(得分:2)
我不确定这会起作用。如果GC移动你在闭包中捕获的对象,那将是非常难看的。也许你必须禁用GC。 http://www.sbcl.org/manual/Calling-Lisp-From-C.html#Calling-Lisp-From-C
也许一个选项是在回调中调用另一个Lisp函数来设置一个变量,但为了使它工作,Lisp函数的地址不应该改变。我不知道在垃圾收集过程中或重新定义函数时,lisp函数的地址是否可以更改。
回调不可移植: http://common-lisp.net/project/cffi/manual/html_node/Tutorial_002dCallbacks.html
如果您的实现支持回调,您可以在此处查看: http://common-lisp.net/project/cffi/manual/html_node/Implementation-Support.html#Implementation-Support
我修改了CFFI帮助中的一个例子。回调函数是比较运算符,它调用一个函数来打印出它所做的每个比较。您可以将其推送到全局变量(或闭包)中,而不是打印列表PAR。
请注意,我不相信这种用法是保存。如果出于某种原因,STORE的位置在内存中发生变化,并且回调函数中的代码没有相应更新,则可能导致错误的结果。
(require :cffi)
(defpackage :run
(:use :cl :cffi))
(in-package :run)
(defcfun "qsort" :void
(base :pointer)
(nmemb :int)
(size :int)
(fun-compar :pointer))
(defun store (par)
(format t "I'm comparing ~a~%" par))
(defcallback < :int ((a :pointer) (b :pointer))
(let ((x (mem-ref a :int))
(y (mem-ref b :int)))
(store (list x y))
(cond ((> x y) 1)
((< x y) -1)
(t 0))))
(with-foreign-object (array :int 10)
;; Initialize array.
(loop for i from 0 and n in '(7 2 10 4 3 5 1 6 9 8)
do (setf (mem-aref array :int i) n))
;; Sort it.
(qsort array 10 (foreign-type-size :int) (callback <))
;; Return it as a list.
(loop for i from 0 below 10
collect (mem-aref array :int i)))
这是示例的输出:
I'm comparing (7 2)
I'm comparing (4 3)
I'm comparing (10 3)
I'm comparing (10 4)
I'm comparing (2 3)
I'm comparing (7 3)
I'm comparing (7 4)
I'm comparing (7 10)
I'm comparing (5 1)
I'm comparing (9 8)
I'm comparing (6 8)
I'm comparing (1 6)
I'm comparing (5 6)
I'm comparing (2 1)
I'm comparing (2 5)
I'm comparing (3 5)
I'm comparing (4 5)
I'm comparing (7 5)
I'm comparing (7 6)
I'm comparing (7 8)
I'm comparing (10 8)
I'm comparing (10 9)
我搜索了freenode #lisp频道日志日志的回调:
http://ccl.clozure.com/irc-logs/lisp/2010-04/lisp-2010.04.28.txt
Best comment there:
12:56:53 <pkhuong> and if you find out that threads are indeed an issue, I'd code a C wrapper to build a message queue.
也许这些代码示例已被更正(我现在无法检查,因为服务器已关闭):
http://paste.lisp.org/display/98482
http://paste.lisp.org/display/98495