0

Say I have this metatable for a custom struct vector2_t which is inside a module mymod like this:

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

And in another script I have this callback/event listener function which must receive a vector2_t as it's argument:

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

Now, I must call that callback/event listener function from C/C++ and pass an instance of that vector2_t (along with it's associated metatable) as the parameter to that function.

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));
    }
}

I'm a bit lost and I don't know how to pas an instance of that vector2_t as the function parameter. I'm sorry for posting so much code bu I wanted to be sure that I explained correctly.

greatwolf
  • 20,287
  • 13
  • 71
  • 105
SLC
  • 2,167
  • 2
  • 28
  • 46

1 Answers1

0

cdata and userdata are completely different things. The only interaction they have is that you can get an FFI void* pointer to userdata. Notably, there is no C API for cdata objects. Mixing them is sure to cause you a lot of headaches.

Pick either the Lua C API or the FFI, and stick to it as much as possible.


To directly answer your question:

how to pas [sic] an instance of that vector2_t as the function parameter

To a Lua C API function, it gets passed on the stack, just like other values. Note that it will be a cdata typed object, not a userdata object. Notably, you can't get a pointer to it.

How do I get the meta table vector2_t on to the stack?

You can't, since you don't make the metatable accessible to outside scripts in your first script. luaL_getmetatable only works with metatables created with luaL_newmetatable

Colonel Thirty Two
  • 23,953
  • 8
  • 45
  • 85