我正在尝试为日晷CVODE库编写CFFI包装器。SWIG被Sundials的头卡住了,因为它们是相互关联的,但是没有找到正确的标题,所以我手工完成了它:有点辛苦,但我已经成功了。
现在我试着测试它是否正确。现在,只需创建"problem对象“并删除它。这就是问题开始的地方。因此,通过函数分配“问题对象”。
SUNDIALS_EXPORT void *CVodeCreate(int lmm, int iter);为此我创建了包装器:
(cffi:defcfun "CVodeCreate" :pointer
(lmm :int)
(iter :int))PS。SUNDIALS_EXPORT (至少在Unix上)基本上是没有意义的。
现在,为了销毁这个对象,Sundials使用了它自己的功能:
SUNDIALS_EXPORT void CVodeFree(void **cvode_mem);因此,我需要将引用传递给CVodeCreate创建的对象。在C语言中,如果我的内存不是错误的,我就会做一些类似CVodeFree(&problem_object)的事情。在CL中,我为函数编写了这个包装器:
(cffi:defcfun "CVodeFree" :void
(cvode-mem :pointer))因此,这里COVDE-MEM是指向指针的指针。问题是如何在CL/CFFI中得到指针?下面是代码的开头:
(defvar *p* (cvodecreate 1 2))(PS. )不要担心传递给CVODECREATE的数字,它们只是告诉要使用哪些方法,仍然需要定义常量以提高其可读性)
所以*P*就像
#.(SB-SYS:INT-SAP #X7FFFE0007060)如果我直接将它传递给CVODEFREE,它将以错误告终:
CL-USER> (cvodefree *p*)
; Evaluation aborted on #<SIMPLE-ERROR "bus error at #X~X" {1005EC9BD3}>.我尝试过通过(CFFI:POINTER-ADDRESS *P*),但是它会导致类似的“总线错误.”(甚至不确定此函数是否返回我所需的内容)。我也尝试过做(CFFI:MAKE-POINTER (CFFI:POINTER-ADDRESS *P*)),但还是没有成功。
这个问题建议采用这种方法:
(cffi:with-foreign-object (p :pointer)
(setf (cffi:mem-ref p :pointer) (cvodecreate 1 2))
(cvodefree p))这是可行的(至少它不会抛出错误)。我想我理解它是如何工作的:它创建(分配内存)一个指针到指针的P,它的MEM-REF (或者用C术语来说是取消引用*p)由CVODECREATE上的结果填充。最后,我将这个指针传递给CVODEFREE,这正是我所期望的。最后,一旦表单完成,为P分配的内存将被释放。这是正确的做法吗?这是我唯一能接受的吗?
发布于 2016-07-26 15:07:56
是的,您的方法看起来是正确的,这里有一个小测试来展示可以直接从repl运行的概念。
(let* (;; a float
(v0 32s0)
;; a pointer to a float foreign memory
(p0 (cffi:foreign-alloc :float :initial-element v0)))
;; a new pointer
(cffi:with-foreign-object (p1 :pointer)
;; make the new pointer point to the first pointer
(setf (cffi:mem-aref p1 :pointer) p0)
;; dereferencing twice should give you the original number
(cffi:mem-aref (cffi:mem-aref p1 :pointer) :float)))附注:我相信你现在已经知道了,很抱歉花了这么长时间才得到答案。希望这能帮助到其他人
https://stackoverflow.com/questions/35841771
复制相似问题