在C++和Lua之间来回发送变量指针?

Kar*_*arl 1 c++ variables scripting lua pointers

我正在寻找一种在C++和Lua之间来回传输变量地址的方法.例如,将对象从C++传输到Lua并进行一些处理,然后将其传回C++.

但是,问题是如何从Lua执行C++函数或方法?或者需要解决方法吗?

如果可能的话,您是否可以添加一个代码段来向我展示它是如何完成的?

我知道我还没有完全理解整个画面,所以如果有什么不妥,请纠正我.

Nic*_*unt 9

我花了很多时间来让Lua与C++类一起工作.Lua比C++更像是一个C风格的API,但有很多方法可以将它与C++一起使用.

在Lua C API中,指针由userdata(或轻用户数据表示,它没有元表并且不是垃圾回收).Userdata可以与metatable相关联,它在Lua中有点像一个类.作为该元表的一部分的C函数包装了c ++类的方法,并充当Lua中的类的方法.

考虑具有私有成员名称(ac字符串)和年龄(int)的基本人员类.名称由构造函数设置,不能更改.年龄暴露于getter和setter:

class person
{
  private:  
    const char* name;
    int age;
  public:
    person(const char* n) {
        name = strdup(n);
    }
    ~person() {
        free((void*)name);
    }
    void print() {
        printf("%s is %i\n",name, age);
    }
    int getAge() {
        return this->age;
    }
    void setAge(int a) {
        this->age=a;
    }
};
Run Code Online (Sandbox Code Playgroud)

为了首先将这个暴露给Lua,我将为符合lua_CFunction原型的所有方法编写包装函数,该原型将lua状态作为参数,并返回一个int,表示它推送到堆栈的值的数量(通常为1或0) ).

这些函数中最棘手的是构造函数,它将返回一个像对象一样的Lua表.为此,lua_newuserdata用于创建指向对象指针的指针.我将假设我们将在Lua init期间创建一个包含这些c函数的元表"Person".此元表必须与构造函数中的userdata相关联.

// wrap the constructor
int L_newPerson(lua_State* L) {
    //pointer to pointer
    person **p = (person **)lua_newuserdata(L, sizeof(person *));
    //pointer to person
    *p = new person(lua_tostring(L, 1)); 
    // associate with Person meta table
    lua_getglobal(L, "Person"); 
    lua_setmetatable(L, -2); 
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

创建其他方法时,您只需记住第一个参数将始终是指向我们使用newPerson创建的指针的指针.为了从中获取C++对象,我们只是从lua_touserdata(L,1);中取消引用返回.

int L_print(lua_State* L) {
    person** p = (person**) lua_touserdata(L, 1);
    (*p)->print();
    return 0;
}

int L_getAge(lua_State* L) {
    person** p = (person**) lua_touserdata(L, 1);
    lua_pushnumber(L, (*p)->getAge());
    return 1;
}

int L_setAge(lua_State* L) {
    person** p = (person**) lua_touserdata(L, 1);
    (*p)->setAge(lua_tonumber(L, 2));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

最后,在初始化Lua期间使用luaL_register设置Person元表.

// our methods...
static const luaL_Reg p_methods[] = {
    {"new", L_newPerson},{"print", L_print},
    {"getAge", L_getAge},{"setAge", L_setAge}, 
    {NULL, NULL}
};

lua_State* initLuaWithPerson() {
    lua_State* L=lua_open();
    luaL_openlibs(L);
    luaL_register(L, "Person", p_methods);  
    lua_pushvalue(L,-1);
    lua_setfield(L, -2, "__index"); 
    return L;
}
Run Code Online (Sandbox Code Playgroud)

并测试它...

const char* Lua_script = 
    "p1=Person.new('Angie'); p1:setAge(25);"
    "p2=Person.new('Steve'); p2:setAge(32);"
    "p1:print(); p2:print();";

int main() {
    lua_State* L=initLuaWithPerson();
    luaL_loadstring(L, Lua_script);
    lua_pcall(L, 0, 0, 0);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

还有其他方法可以在Lua中实现OO.本文介绍了替代方案:http: //loadcode.blogspot.com/2007/02/wrapping-c-classes-in-lua.html