2016-03-07 40 views
5

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によって作成されたオブジェクトへの参照を渡す必要があります:

は今、オブジェクトを破壊するために、日時計は、独自の機能を使用しています。 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*))をやろうとしましたが、もう一度成功することはありません。

This questionは、このアプローチを提案している:

(cffi:with-foreign-object (p :pointer) 
      (setf (cffi:mem-ref p :pointer) (cvodecreate 1 2)) 
      (cvodefree p)) 

これは動作します(少なくとも、それはエラーをスローしません)。私はそれがどのように動作するかを理解していると思います。ポインタPMEM-REF(またはCの用語では逆参照である*p)のポインタがCVODECREATEの結果で埋められます。最後に、私はこのポインタをCVODEFREEに渡します。これはまさにこれを期待しています。最後に、Pに割り当てられたメモリは、フォームが終了すると解放されます。これは正しいアプローチですか?それは私が取ることができる唯一のものですか?

+0

なぜ彼らが 'CVodeFree'のためにその署名を選んだのか知っているでしょうか。 "オーバーエンジニアリング"のように見え、余分に賢いようにしようとしています。 –

+0

@DanielJour私がこのように覚えている限り、C世界では珍しいことではありません。おそらく、彼らはメモリを解放し、そこでポインタをNULLにします。しかし、私は同意する、全く不要です。 – mobiuseng

答えて

2

あなたのアプローチは正しいと思われますが、ここでは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))) 

p.s.私はあなたが今これを知っていたと確信しています、申し訳ありませんが、それはあなたに答えを得るまでにかかった。うまくいけば、これは他人を助けることができます

関連する問題