注册一个c++类以便在Lua 5.2中使用

Registering a C++ class for use in Lua 5.2

本文关键字:Lua 一个 c++ 注册      更新时间:2023-10-16

所以我正在阅读如何通过这个小博客教程为Lua创建和注册一个c++类。

但是,尽管它简单、信息丰富、易读,但它似乎是为旧版本的Lua编写的。

所以一些函数/宏要么缺失,要么只是有不同的签名。

下面的代码在Lua C版本5.2中会是什么样子?

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <stringstream>
#include <string>
using namespace std;
// Just a useless test class
class MyClass
{
private:
    int _X;
public:
    MyClass(int x) : _X(x) {};
    ~MyClass() { Release() };
    // Displays your number in a welcoming message box
    void Hello()
    {
        stringstream ss;
        ss << "Hello!" << endl << "Your number is: " << _X;
        string s(ss.str());
        MessageBoxA(NULL, s.c_str(), "MyClass", MB_ICONINFORMATION);
    }
    void Release() {
        //release code goes here
    }
};
// Functions that will create/destroy MyClass instances
static int newMyClass(lua_State* L)
{
    int n = lua_gettop(L); // Number of arguments
    if (n != 2)
        return luaL_error(L, "Got %d arguments, expected 2 (class, x)", n);
    // First argument is now a table that represent the class to instantiate
    luaL_checktype(L, 1, LUA_TTABLE);
    lua_newtable(L); // Create table to represent instance
    // Set first argument of new to metatable of instance
    lua_pushvalue(L, 1);
    lua_setmetatable(L, -2);
    // Do function lookups in metatable
    lua_pushvalue(L, 1);
    lua_setfield(L, 1, "__index");
    // Allocate memory for a pointer to to object
    MyClass** s = (MyClass**)lua_newuserdata(L, sizeof(MyClass*));
    int x = luaL_checknumber(L, 2);
    *s = new MyClass(x);
    luaL_getmetatable(L, "Lua.MyClass");
    lua_setmetatable(L, -2);
    lua_setfield(L, -2, "__self");
    return 1;
}
static int doSomethingMyClass(lua_State* L)
{
    MyClass* c = nullptr;
    checkUserData(L, "Lua.MyClass", c);
    c->Hello();
    return 0;
}
static int destroyMyClass(lua_State* L)
{
    MyClass* c = nullptr;
    checkUserData(L, "Lua.MyClass", c);
    c->Release();
    return 0;
}
// Functions that will show up in our Lua environment
static const luaL_Reg gMyClassFuncs[] = {
    // Creation
    { "new", newMyClass) },
    { "hello", helloMyClass },
    { NULL, NULL }
};
static const luaL_Reg gDestroyMyClassFuncs[] = {
    {"__gc", destroyMyClass},
    {NULL, NULL}
};
// Registers the class for use in Lua
void registerMyClass(lua_State *L)
{  
    // Register metatable for user data in registry
    luaL_newmetatable(L, "Lua.MyClass");
    luaL_register(L, 0, gDestroyMyClassFuncs);      
    luaL_register(L, 0, gMyClassFuncs);      
    lua_pushvalue(L, -1);
    lua_setfield(L, -2, "__index");  
    // Register the base class for instances of Sprite
    luaL_register(L, "MyClass", gSpriteFuncs);  
}


基本上,这里的目标是能够用Lua编写以下内容:

-- Create a new MyClass instance
local c = MyClass:new(5)
-- Show message
c:Hello() -- Should say something like "Hello! Your number is: 5"

我需要改变什么为了使这个工作在5.2?

该代码中唯一不属于Lua 5.2的函数是luaL_register。你应该用luaL_setfuncs代替。

您还应该手动设置全局MyClass或在Lua代码中使用local MyClass=require"MyClass",因为require不再设置全局。

如果你正在嵌入Lua,你可以用-DLUA_COMPAT_MODULE编译它和你的代码,并得到5.1函数。但是,如果您打算使用Lua 5.2,那么现在是将代码迁移到该版本的好时机。