寄存器 C++ Lua 中的函数?

发布于 2024-12-14 15:44:53 字数 892 浏览 2 评论 0原文

我正在尝试在 Lua 中注册一个 C++ 函数。

但出现此错误:

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

编辑:

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

并且在主要内容中:

lua_register(L, "setDisplayMode", Lua_SetDisplayMode);

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

半暖夏伤 2024-12-21 15:44:53

不能将类的方法用作普通函数,除非将其声明为static。你必须定义一个普通的函数,它找出你想要在哪个对象中调用该方法,然后调用该方法。

无法使用类方法作为 C 函数的回调(请记住 Lua API 是纯 C 库)的主要原因是计算机不知道应该在哪个对象上调用该方法。

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.

乖乖 2024-12-21 15:44:53

答案其实出奇的简单;如果您使用 lua_pushcclosure 而不是 lua_pushcfunction,则可以将参数传递给被调用的函数:

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

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);
    }
初相遇 2024-12-21 15:44:53

仅使用基本的 Lua C API 无法直接在 Lua 中注册 C++ 非静态成员函数。

然而,任何可以轻松将 C++ 代码与 Lua 关联起来的各种机制都可以让您这样做。 toLua++, SWIGLuabind 等。如果您认真对待使用 C++ 对象Lua,我建议选择其中之一并使用它,而不是编写自己的版本。我个人使用 Luabind(大多数时候;SWIG 在工具箱中占有一席之地),因为它没有某种形式的代码生成。这一切都是纯粹用 C++ 完成的,因此没有生成 C++ 源文件的预传递步骤。

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.

我要还你自由 2024-12-21 15:44:53

您也可以通过将活动 this 指针存储在静态变量中来解决该限制。这引入了无法同时运行其中两个类的问题,但它是有效的。

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

然后,在您的 CScript 构造函数(或某种“激活”函数)中,您可以指定:

luaThis = this;

然后,当您的静态函数被调用时(如果它们是从内部注册的,它们甚至可以是私有函数)类),您可以通过 luaThis 指针访问所有成员信息。

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

正如我所说,问题在于这限制了您一次只能使用一个活动的 CScript(因为来自另一个 Lua 状态的另一个回调将使用 luaThis,而它指向错误的内容)。如果您需要多个活动实例,您可以使用传入的 lua_State* 作为键来提出一些查找机制。

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

希望有帮助!

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文