创建一个回调结构体,以便传递到LuaJIT FFI中。

首先我加载我需要的一个 DLL:

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

在 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;

我还在 cdef 中定义了这个函数:

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

现在我想调用这个函数:

print(theDLL.start_session(a,b))

变量 a 和 b 显然是占位符,问题是我如何传递函数需要的结构体?而且假设我们让 StructSession 工作,通过 LuaJIT 回调到一个函数,是否对于 StructCallbacks 是可能的?

点赞
用户646619
用户646619

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

创建StructSession则要棘手一些,因为它是一个不透明类型,但它与在C中所做的方式并没有太大区别。

以下是您在C中创建的方式:

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

请注意,您不是直接分配一个StructSession,而是分配一个指向它的指针,并让start_session分配实际的结构。

那么我们现在将其转换为LuaJIT代码:

local S = ffi.new("StructSession*")
lib.start_session(getPointer(S), foo) -- getPointer应该获取S的指针,但…

… FFI没有提供任何获取对象的指针的方法(这是有意为之的,它允许进行优化)。

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

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

现在,您已经拥有了一个StructSession对象。

2014-05-31 15:57:03