创建一个回调结构以传递给LuaJIT FFI

时间:2021-11-09 17:02:59

So first I load in a DLL I need

所以首先我加载一个我需要的DLL

local ffi = require("ffi")
local theDLL = ffi.load("thisDLL")

in the ffi cdef I have two different kinds of structs

在ffi cdef我有两种不同的结构

ffi.cdef [[
    typedef struct StructSession StructSession;
    typedef struct {
        /*
        * begin_proj callback
        */
        bool (__cdecl *begin_proj)(char *proj);

        /*
        * save_proj_state
        */
        bool (__cdecl *save_proj_state)(unsigned char **buffer, int *len);
    } StructCallbacks;

I also have this function in the cdef

我在cdef中也有这个功能

__declspec(dllexport) int __cdecl start_session(StructSession **session,
                                                           StructCallbacks *cb);

Now I would like to call this function

现在我想调用这个函数

print(theDLL.start_session(a,b))

vars a and b are obviously placeholders, the question is how can I pass the structs the function needs? And say we get StructSession working, is making a callback to a function WITHIN LuaJIT even going to be possible for StructCallbacks?

变量a和b显然是占位符,问题是如何传递函数所需的结构?并说我们得到StructSession工作,正在回复一个函数WITHIN LuaJIT甚至可以用于StructCallbacks?

1 个解决方案

#1


6  

Creating the StructCallbacks is easy; you can create it with ffi.new and create FFI callbacks for the fields (see the FFI semantics for information on callbacks).

创建StructCallbacks很容易;您可以使用ffi.new创建它并为字段创建FFI回调(有关回调的信息,请参阅FFI语义)。

Creating the StructSession is trickier since it's an opaque type, but it's not much different from how you would do it in C.

创建StructSession是比较棘手的,因为它是一个不透明的类型,但它与你在C中的方式没有太大的不同。

Here is how you would create one in C:

以下是如何在C中创建一个:

StructSession* S = NULL;
start_session(*S, foo);

Notice how you are not directly allocating a StructSession. Instead, you allocate a pointer to one, and let start_session allocate the actual struct.

请注意您不是直接分配StructSession。相反,你分配一个指针,让start_session分配实际的结构。

So we now translate this to LuaJIT code:

所以我们现在将其转换为LuaJIT代码:

local S = ffi.new("StructSession*")
lib.start_session(getPointer(S), foo) -- getPointer should take the pointer of S, but...

...the FFI doesn't provide any way to take the pointer of an object (This is intentional; it allows for optimizations).

... FFI没有提供任何方法来获取对象的指针(这是故意的;它允许优化)。

So how do we get a pointer to a StructSession? Well, recall that arrays are convertible to pointers, and we can access those through the FFI. So we instead create a single-slot array of pointers and pass that to start_session:

那么我们如何获得指向StructSession的指针?好吧,回想一下,数组可以转换为指针,我们可以通过FFI访问它们。所以我们改为创建一个单槽指针数组并将其传递给start_session:

local S_slot = ffi.new("StructSession*[1]")
lib.start_session(S_slot, foo)
local S = S_slot[0]

And now you have a StructSession object.

现在你有了一个StructSession对象。

#1


6  

Creating the StructCallbacks is easy; you can create it with ffi.new and create FFI callbacks for the fields (see the FFI semantics for information on callbacks).

创建StructCallbacks很容易;您可以使用ffi.new创建它并为字段创建FFI回调(有关回调的信息,请参阅FFI语义)。

Creating the StructSession is trickier since it's an opaque type, but it's not much different from how you would do it in C.

创建StructSession是比较棘手的,因为它是一个不透明的类型,但它与你在C中的方式没有太大的不同。

Here is how you would create one in C:

以下是如何在C中创建一个:

StructSession* S = NULL;
start_session(*S, foo);

Notice how you are not directly allocating a StructSession. Instead, you allocate a pointer to one, and let start_session allocate the actual struct.

请注意您不是直接分配StructSession。相反,你分配一个指针,让start_session分配实际的结构。

So we now translate this to LuaJIT code:

所以我们现在将其转换为LuaJIT代码:

local S = ffi.new("StructSession*")
lib.start_session(getPointer(S), foo) -- getPointer should take the pointer of S, but...

...the FFI doesn't provide any way to take the pointer of an object (This is intentional; it allows for optimizations).

... FFI没有提供任何方法来获取对象的指针(这是故意的;它允许优化)。

So how do we get a pointer to a StructSession? Well, recall that arrays are convertible to pointers, and we can access those through the FFI. So we instead create a single-slot array of pointers and pass that to start_session:

那么我们如何获得指向StructSession的指针?好吧,回想一下,数组可以转换为指针,我们可以通过FFI访问它们。所以我们改为创建一个单槽指针数组并将其传递给start_session:

local S_slot = ffi.new("StructSession*[1]")
lib.start_session(S_slot, foo)
local S = S_slot[0]

And now you have a StructSession object.

现在你有了一个StructSession对象。