2014-06-09 57 views
4

我知道有一些使用LuaJIT FFI創建指針的例子,但其中大多數並不指向現有數據。其中一個例子如下: How to pass a pointer to LuaJIT ffi to be used as out argument?如何使用LuaJIT FFI創建指向現有數據的指針?

有一件事,我沒有能夠成功做到的是創建一個指向現有值的指針。爲了有一個指針類型,據我所知,我要知道,我想在未來的某個時候有一個指針指向它,如:

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,這樣我就可以指定它正常。

換句話說,有沒有辦法獲得現有值的地址或創建指針?在創建它之前,我是否必須預見我將如何處理這些價值?

謝謝!

回答

3

無法獲得指向FFI中的cdata對象的指針。

我記得在LuaJIT郵件列表中讀到,這是有意完成某些優化工作,儘管我無法在檔案中找到確切的消息。

到目前爲止,我還沒有獲得cdata對象的指針; LuaJIT通過引用引用cdata(類似於表),並且type[1]技巧適用於輸出參數。

+0

這就是我所害怕的。我想我只是用這種語法初始化類型!如果我對這種變化過於熱心,我只是擔心數組索引是一個新的性能問題。 –

0

我能做到這一點與C函數那份這樣

void cdataToPointer(void *cdata, void **pointer) { 
    *pointer = cdata; 
} 

// ... 

void *mycdata = NULL; 

lua_pushlightuserdata(L, &mycdata); 
lua_setglobal(L, "__TEMP_USERDATA__"); 

luaL_dostring(L, 
    "local ffi = require'ffi'\n" 
    "ffi.cdef[[\n" 
    " void cdataToPointer(void *cdata, void **pointer);\n" 
    "]]\n" 
    "ffi.C.cdataToPointer(mycdata, __TEMP_USERDATA__)\n"); 
3

,你不能得到一個CDATA對象的地址的原因CDATA指針是所有CDATA對象進行垃圾收集。如果你停下來並認爲通過它的邏輯結論,你會發現這意味着它們必須分配在Lua Heap上,而不是一般的C堆,而這些堆將被用於malloc。只是將指針返回到Lua堆是非常不安全的,因爲垃圾收集器可以隨時來到並移動對象。

這樣做的一個結果是,你絕對不應該做rraallvv建議的,因爲你可能會導致seg-fault。

當調用ffi.new("GLuint[1]")您有關的Lua堆上分配的GLuint秒的陣列(LuaJIT此稱之爲「參考」類型)這是確定因爲當調用到GenVertexArrays()(1)的GC不能運行,因爲你'忙於執行C代碼,(2)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