Pointers 如何使用LuaJIT FFI创建指向现有数据的指针?

Pointers 如何使用LuaJIT FFI创建指向现有数据的指针?,pointers,ffi,luajit,Pointers,Ffi,Luajit,我知道有一些使用LuaJIT FFI创建指针的例子,但大多数都没有指向现有数据。这方面的一个例子如下: 有一件事我没能成功地做到,那就是创建一个指向现有值的指针。就我所知,为了有一个指针类型,我必须知道我希望在将来的某个时候有一个指向它的指针,如: local vao = ffi.new("GLuint[1]") gl.GenVertexArrays(1, vao) gl.BindVertexArray(vao[0]) 在这里,我知道glgenvertexarray需要一个指向vao的指针,

我知道有一些使用LuaJIT FFI创建指针的例子,但大多数都没有指向现有数据。这方面的一个例子如下:

有一件事我没能成功地做到,那就是创建一个指向现有值的指针。就我所知,为了有一个指针类型,我必须知道我希望在将来的某个时候有一个指向它的指针,如:

local vao = ffi.new("GLuint[1]")
gl.GenVertexArrays(1, vao)
gl.BindVertexArray(vao[0])
在这里,我知道glgenvertexarray需要一个指向
vao
的指针,所以我将其指定为GLuint[1]。在C中,我将做如下操作:

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
在这里,我不知道我需要一个指向
vao
的指针,所以我可以正常地指定它

换句话说,是否有方法获取现有值的地址或创建指向现有值的指针?在我创造价值之前,我是否必须预见我将如何利用价值


谢谢

无法在FFI中获取指向cdata对象的指针

我记得在LuaJIT邮件列表中读到,这是为了实现一些优化而特意做的,尽管我在存档中找不到确切的消息


到目前为止,我还不需要获取cdata对象的指针;LuaJIT通过引用引用cdata(类似于表),并且
类型[1]
技巧适用于out参数。

我可以通过一个复制cdata指针的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");

无法获取cdata对象的地址的原因是所有cdata对象都是垃圾收集的。如果您停下来仔细思考,直到得出它的逻辑结论,您将看到这意味着它们必须分配到Lua堆上,而不是
malloc
将使用的一般C堆上。仅仅将指针返回到Lua堆是非常不安全的,因为垃圾收集器可能随时出现并移动对象

这样做的一个后果是,您绝对不应该执行rraallvv建议的操作,因为您可能会导致seg故障

当您调用
ffi.new(“GLuint[1]”)时,可以在Lua堆上分配一个
GLuint
s数组(LuaJIT称之为“引用”类型),因为当您调用
genvertexarray()
(1)GC无法运行,因为您正忙于执行C-code,(2)
genvertexarray()
没有保留指针,因此,您不必担心以后会访问过时的指针

然而,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

这就是我害怕的。我想我将使用该语法初始化类型!我只是担心数组索引会成为一个新的性能问题,如果我对这个更改过于热心的话。