5

日時計 CVODEライブラリの CFFI ラッパーを作成しようとしています。SWIG は Sundials のヘッダーがかなり相互接続されており、SWIG が適切なヘッダーを見つけられなかったため、窒息していました。

今、私はそれが正しく動作するかどうかをテストしようとしています. 今のところ、単に「問題オブジェクト」を作成して削除するだけです。そこから問題が始まります。したがって、「問題オブジェクト」は関数を介して割り当てられます

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*pCVODECREATECVODEFREEP

4

1 に答える 1