简体   繁体   中英

Register C++ function in Lua?

I am trying to register a c++ function in Lua.

But getting this error:

CScript.cpp|39|error: argument of type 'int (CScript::)(lua_State*)' does not match 'int (*)(lua_State*)'|

EDIT:

int CApp::SetDisplayMode(int Width, int Height, int Depth)
{
    this->Screen_Width = Width;
    this->Screen_Height = Height;
    this->Screen_Depth = Depth;

    return 0;
}

int CScript::Lua_SetDisplayMode(lua_State* L)
{
  // We need at least one parameter
  int n = lua_gettop(L);
  if(n < 0)
  {
    lua_pushstring(L, "Not enough parameter.");
    lua_error(L);
  }

  int width = lua_tointeger(L, 1);
  int height = lua_tointeger(L, 2);
  int depth = lua_tointeger(L, 3);

  lua_pushinteger(L, App->SetDisplayMode(width, height, depth));

  return 0;
}

And in main:

lua_register(L, "setDisplayMode", Lua_SetDisplayMode);

You can not use a method of a class as a normal function, unless it is declared static . You have to define a normal function, which finds out what object you want the method to be called in, and then call the method.

The main reason it's not possible to use a class method as a callback from a C function (and remember that the Lua API is a pure C library), is because the computer doesn't know which object the method should be called on.

The answer is actually surprisingly simple; if you use lua_pushcclosure instead of lua_pushcfunction, you can pass parameters to your called function:

    lua_pushlightuserdata(_state, this);
    lua_pushcclosure(_state, &MyClass::lua_static_helper, 1);

    int MyClass::lua_static_helper(lua_State *state) {
        MyClass *klass = (MyClass *) lua_touserdata(state, lua_upvalueindex(1));
        return klass->lua_member_method(state);
    }

You cannot directly register a C++ non-static member function in Lua using just the basic Lua C API.

However, any of the various mechanisms that exist for easily associating C++ code with Lua will allow you to do so. toLua++ , SWIG , Luabind , etc. If you're serious about using C++ objects with Lua, I suggest picking one of those and using it, rather than writing your own version. I personally use Luabind (most of the time; SWIG has its place in the toolbox), as it is the one that doesn't have some form of code generation. It's all done purely in C++, so there's no pre-pass step that generates a C++ source file.

You can work around the limitation by storing your active this pointer in a static variable as well. This introduces the problem of being unable to have two of these classes operating at the same time, but it works.

static CScript* luaThis; // This is a private variable inside CScript.

Then, inside your CScript constructor (or some kind of 'activate' function), you can just specify:

luaThis = this;

Then, when your static functions are called (they can even be private functions if they are registered from within the class), you have access to all your member information via the luaThis pointer.

lua_pushinteger(L, luaThis->App->SetDisplayMode(width, height, depth));

The problem, as I said, is that this restricts you to one active CScript at a time (since another callback from another Lua state would use luaThis while it is pointing to the wrong things). If you need multiple active instances ever, you can come up with some lookup mechanism using the incoming lua_State* as a key.

std::map<lua_State*, CScript*> lookups; // Just an idea, if it comes to this.

Hope that helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM