8

I have a C++ project, where 1 method of a 1 class changes very often. So I want to take that code from C++ to Lua. Note, I'm novice to Lua.

The whole task:

  1. Bind some class methods to Lua state machine;
  2. Pass reference to class object to a function, written in Lua;
  3. Operate with passed C++ object in Lua function.

I've found how to make first step with Lunar, and can't cope with second and third.

I can't use SWIG and boost.

3 Answers 3

8
//This has a large number of steps, but I'm gonna post them all. This is all using native Lua 5 and the lua CAPI.
int CreateInstanceOfT(lua_State* L) {
    new (lua_newuserdata(L, sizeof(T))) T(constructor args);
    return 1;
}
int CallSomeFuncOnT(lua_State* L) {
    if (lua_istable(L, 1)) { // If we're passed a table, get CData
        lua_getfield(L, 1, "CData");
        lua_replace(L, 1);
    }
    if (!lua_touserdata(L, 1))
        lua_error(L); // longjmp out.
    T& ref = *(T*)lua_touserdata(L, 1);
    ref.SomeFunc(); // If you want args, I'll assume that you can pass them yourself
    return 0;
}
int main() {
    lua_State* L = luaL_newstate();
    lua_pushcfunction(L, CreateInstanceOfT);
    lua_setglobal(L, "CreateInstanceOfT");
    lua_pushcfunction(L, CallSomeFuncOnT);
    lua_setglobal(L, "CallSomeFuncOnT");
    luaL_dofile(L, "something.lua");
    lua_close(L);
}
-- Accompanying Lua code: semicolons are optional but I do out of habit. In something.lua
function CreateCInstance()
    local Instance = {
        CData = CreateInstanceOfT();
        SomeFunc = CallSomeFuncOnT;
    }
    return Instance;
end

local object = CreateCInstance();
object:SomeFunc(); // Calls somefunc.

I could post a great quantity of detail about how to make exposure easier, and how to make inheritance, and suchlike - and it'll need altering if you want to expose more than one T (I think the most common solution is a simple struct { std::auto_ptr<void>, int type } deal). But, it should be a starting point if you don't understand anything about this process.

Bascally, first, we ask Lua to allocate some space (the userdata), then put T in it. When CallSomeFuncOnT comes up, first we ask it if we have a table (many Lua classes are based around tables, as they support object orientation, metatables, and such), and get the userdata out, which we then convert into a pointer to our object, and then convert into a reference. Remember that lua_touserdata gives you a void*, so you'd better be damn sure about what's on the other end. Then we call somefunc and return. In Main, we just register the functions as globals.

Now, in Lua, when you call CreateInstanceOfT, it effectively just calls the T constructor, transparently to the Lua user. Then we ditch it in a table, which is simpler for Lua novices, and call SomeFunc by passing it this table.

Sign up to request clarification or add additional context in comments.

2 Comments

Am I wrong, or is it true that T's destructor never gets called using this technique? As I understand it, Lua doesn't know anything about C++ objects and simply calls free for memory it controls, such as that allocated by lua_newuserdata.
Pretty sure that I definitely left that part out. Probably along with many other useful parts.
1

Have you taken a look at luabind? It makes it fairly easy to expose C++ objects and functions to LUA.

1 Comment

Yes, I have. As mentioned on rasterbar.com/products/luabind/docs.html it uses boost
1

Like John, I've used luabind and recommend it. However, since using boost isn't an option for you, you may find the list of libraries on this page helpful. You may also want to check out the DoItYourselfCppBinding page on the lua-users wiki.

One library mentioned on the page is oolua, which has no dependencies (so it says).

2 Comments

I just can't believe, that I need some library for such an easy operation.
Keep in mind that you can always use the Lua C API and do the binding yourself. The libraries are there to make it "easier" to bind C++ classes to Lua.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.