2014-09-07 5 views
0

Скажет, у меня есть эта метатаблица для настраиваемого структуры vector2_t, который находится внутри модуля MyMod так:LuaJIT - Получить метатаблицу из модуля/пакета и присвоить его USERDATA

local mymod = {} 

local ffi = require("ffi") 
local C = ffi.C 

ffi.cdef[[ 
    typedef struct 
    { 
     double x; 
     double y; 
    } vector2_t; 
]] 

local vector2_t 

vector2_t = ffi.metatype("vector2_t", { 
    __eq = function(lhs, rhs) 
     if lhs.x == rhs.x and lhs.y == rhs.y 
     then return true else return false end 
    end 
    -- Member functions follow... 
}) 

vcmp.vector2 = vector2_t 

-- I use this method because the script is integrated in C/C++ as a string and not 
-- as a file and I need a constant name that isn't decided by the file name 

package.preload["mymod"] = function(mod) return mymod end 

И в другом сценарии у меня есть этот обратный вызов/событие функция прослушивателя, который должен получить vector2_t, как это аргумент:

local mymod = require "mymod" 

local some_pos = mymod.vector2(32, 29.7) 

-- That pos argument must be an instance of mymod.vector2_t 
function position_update(pos) 
    print("New Pos: " .. pos.x .. ", " .. pos.y .. "\n") 
    some_pos.x = pos.x 
    some_pos.y = pos.y 
end 

Теперь, я должен вызвать эту функцию обратного вызова слушателя/событие из C/C++ и передать экземпляр этого vector2_t (вместе с его метатабельностью) в качестве параметра этой функции.

typedef struct 
{ 
    double x; 
    double y; 
} vector2_t; 

void call_position_update(lua_State* L, double x, double y) 
{ 
    // Retrieve the function 
    lua_getglobal(L, "position_update"); 

    // Validate it 
    if (!lua_isfunction(L, lua_gettop(L))) 
    { 
     lua_pop(L, 1); 
     return;  
    } 

    // Create an instance of vector2_t 
    vector2_t *pos = (vector2_t *)lua_newuserdata(L, sizeof(vector2_t)); 

    // Assign the values to the new instance 
    pos->x = x; 
    pos->y = y; 

    // How do I get the meta table vector2_t on to the stack? 
    // Reach to the module somehow... 

    // Get the meta table from the module 
    luaL_getmetatable(L, "vector2_t"); 
    // Assign the meta table to the vector2_t instance already on the stack 
    lua_setmetatable(L, -2); 

    // I'm assuming that the vector2_t instance is already on the stack so there's nothing else to push 

    // Call the function with 1 argument which should be that vector2_t onto the stack 
    if (!lua_pcall(L, 1, 0, 0)) 
    { 
     printf("Error calling function 'position_update': %s\n", lua_tostring(_Lua, -1)); 
    } 
} 

Я немного потерял, и я не знаю, как па экземпляр этого vector2_t в качестве параметра функции. Мне жаль, что вы разместили столько кода, что я хотел быть уверенным, что правильно объяснил.

ответ

0

cdata и userdata - это совершенно разные вещи. Единственное, что у них есть, это то, что вы можете получить указатель FFI void* на пользовательские данные. Примечательно, что нет API C для объектов cdata. Смешение их обязательно вызовет у вас много головных болей.

Выберите либо API Lua C, либо FFI, и придерживайтесь его как можно больше.


Чтобы получить ответ на ваш вопрос:

как PAS [так в оригинале] экземпляр этого vector2_t в качестве параметра функции

к функции API Lua C, она будет передана в стеке, как и другие значения. Обратите внимание, что это будет типизированный объект cdata, а не объект userdata. Примечательно, что вы не можете получить указатель на него.

Как получить таблицу meta table2_t в стек?

Вы не можете, так как вы не делаете доступный доступный для внешних скриптов в своем первом скрипте доступным для метаданных. luaL_getmetatable работает только с метаданными, созданными с помощью luaL_newmetatable