Sundials CVODEライブラリのCFFIラッパーを記述しようとしています。 SWIGはSundialsのヘッダーではかなり相互接続されており、SWIGは適切なヘッダーを見つけることができなかったので窒息していたので、手作業でやった。Common Lisp CFFI:ポインタへのポインタ
これは正しく動作するかどうかをテストしようとしています。今のところ、単に「問題オブジェクト」を作成して削除するだけです。それが問題の始まりです。
(cffi:defcfun "CVodeCreate" :pointer
(lmm :int)
(iter :int))
PS:だから、 "問題のあるオブジェクトは、" 私はラッパーを作成した機能
SUNDIALS_EXPORT void *CVodeCreate(int lmm, int iter);
を経由して割り当てられています。 SUNDIALS_EXPORT
(少なくともUnix上では)基本的には何もありません。
SUNDIALS_EXPORT void CVodeFree(void **cvode_mem);
だから、私はそれをCVodeCreate
によって作成されたオブジェクトへの参照を渡す必要があります:
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*))
をやろうとしましたが、もう一度成功することはありません。
This questionは、このアプローチを提案している:
(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
に割り当てられたメモリは、フォームが終了すると解放されます。これは正しいアプローチですか?それは私が取ることができる唯一のものですか?
なぜ彼らが 'CVodeFree'のためにその署名を選んだのか知っているでしょうか。 "オーバーエンジニアリング"のように見え、余分に賢いようにしようとしています。 –
@DanielJour私がこのように覚えている限り、C世界では珍しいことではありません。おそらく、彼らはメモリを解放し、そこでポインタをNULLにします。しかし、私は同意する、全く不要です。 – mobiuseng