4

LuaJIT FFI を使用してポインターを作成する例があることは知っていますが、これらのほとんどは既存のデータを指していません。そのような例の 1 つがここにあります: LuaJIT ffi にポインターを渡し、out 引数として使用する方法は?

私がうまくできていないことの 1 つは、既存の値へのポインターを作成することです。私の知る限り、ポインター型を持つためには、次のように、将来のある時点でそれを指すポインターが必要であることを知っておく必要があります。

local vao = ffi.new("GLuint[1]")
gl.GenVertexArrays(1, vao)
gl.BindVertexArray(vao[0])

ここで、glGenVertexArrays には へのポインターが必要であることがわかっているvaoので、GLuint[1] として指定します。Cでは、次のようなことをしています:

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

ここでは、 へのポインタが必要になるとは考えていないvaoので、普通に指定できます。

つまり、既存の値のアドレスを取得したり、ポインタを作成したりする方法はありますか? 値を作成する前に、その値で何をするかを予測する必要がありますか?

ありがとう!

4

3 に答える 3

4

cdata オブジェクトのアドレスを取得できない理由は、すべての cdata オブジェクトがガベージ コレクションされているためです。立ち止まって論理的な結論まで考えると、これは、使用する一般的な C ヒープではなく、Lua ヒープに割り当てる必要があることを意味することがわかりますmalloc。ポインターを Lua ヒープに返すだけでは、ガベージ コレクターがいつでもオブジェクトを移動する可能性があるため、非常に安全ではありません。

この結果の 1 つは、seg-fault を引き起こす可能性があるため、rraallvv が提案したことを絶対に行うべきではないということです。

を呼び出すと、Lua ヒープffi.new("GLuint[1]")に s の配列が割り当てられます ( LuaJITGLuintはこれを「参照」型と呼びます) (1)を呼び出すと、C コードの実行に忙しいため、GC を実行できないため、これは問題ありません ( 2)ポインターを保持しないため、古いポインターが後でアクセスされることを心配する必要はありません。GenVertexArrays()GenVertexArrays()

ただし、LuaJIT の FFI は、独自の割り当ての仕組みを構築できる十分な機能を提供します。次のコードは (このバージョンを正確にテストしていません) C ヒープにデータを割り当て、デフォルトのファイナライザーをインストールして解放する必要があります。使用されているすべての FFI 関数を調べると、物事がよりよく理解できるはずです。

local function SafeHeapAlloc(typestr, finalizer)
  -- use free as the default finalizer
  if not finalizer then finalizer = ffi.C.free end

  -- automatically construct the pointer type from the base type
  local ptr_typestr = ffi.typeof("$ *", typestr)

  -- how many bytes to allocate?
  local typesize    = ffi.sizeof(typestr)

  -- do the allocation and cast the pointer result
  local ptr = ffi.cast(ptr_typestr, ffi.C.malloc(typesize))

  -- install the finalizer
  ffi.gc( ptr, finalizer )

  return ptr
end
于 2015-05-27T02:46:00.350 に答える
3

FFI で cdata オブジェクトへのポインターを取得する方法はありません。

LuaJIT メーリング リストで、これはいくつかの最適化が機能するように意図的に行われたことを読んだことを覚えていますが、アーカイブで正確なメッセージを見つけることはできません。

これまでのところ、cdata オブジェクトのポインターを取得する必要はありませんでした。LuaJIT は参照によって cdata を参照し (テーブルと同様)、type[1]out パラメーターに対してトリックが機能します。

于 2014-06-09T04:12:26.110 に答える