How can I create a pointer to existing data using the LuaJIT FFI?

后端 未结 3 994
情深已故
情深已故 2021-01-19 14:50

I know there are examples of creating pointers using the LuaJIT FFI, but most of these aren\'t pointed to existing data. One such example of this is here: How to pass a poin

3条回答
  •  北海茫月
    2021-01-19 15:26

    The reason that you can't get the address of a cdata object is that all cdata objects are garbage collected. If you stop and think that through to its logical conclusion, you'll see this means that they must be allocated on the Lua Heap, rather than the general C heap that malloc would use. It's highly unsafe to just return pointers into the Lua heap because the garbage collector could come along and move the object at any time.

    One consequence of this is that you absolutely should not do what rraallvv suggested, since you're likely to cause a seg-fault.

    When you call ffi.new("GLuint[1]") you allocate an array of GLuints on the Lua heap (LuaJIT calls this a 'reference' type) This is ok because when you call into GenVertexArrays() (1) the GC cannot run, since you're busy executing C-code, (2) GenVertexArrays() doesn't retain the pointer, so you don't have to worry about a stale pointer being accessed later.

    However, LuaJIT's FFI provides enough features that we can build our own allocation contraptions. The following code should (haven't tested this version exactly) allocate data on the C heap and install a default finalizer to free it. If you look up all the FFI functions used, you should get a better sense of things.

    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
    

提交回复
热议问题