【发布时间】:2018-07-08 18:38:16
【问题描述】:
我想知道是否可以从 Lua 脚本中使用的绑定 C++ 类访问运行 Lua 脚本的类的变量。
从下面的示例中,我想知道是否可以从绑定的Test 类中以某种方式访问myLua 类中的name 变量。
这是我的代码。
main.cpp:
extern "C"
{
int luaopen_my(lua_State* L);
}
class myLua {
public:
struct myData
{
std::string name;
lua_State *L;
};
myLua(std::string name)
{
data = make_shared<myData>();
data->name = name;
data->L = luaL_newstate();
lua_State *L = data->L;
luaL_openlibs(L);
luaopen_my(L);
lua_settop(L, 0);
const char *script =
"function setup() \
test = my.Test() \
test:callHello() \
end \
function hello(name) \
print('hello is called by : ' .. name) \
end";
//------------Added----------------
lua_pushlightuserdata(L, data.get());
myLua::myData *b = static_cast<myLua::myData *>(lua_touserdata(L, 1));
cout << "RESULT1 : " << b->name << endl;
//---------------------------------
const int ret = luaL_loadstring(L, script);
if (ret != 0 || lua_pcall(L, 0, LUA_MULTRET, 0) != 0)
{
std::cout << "failed to run lua script" << std::endl;
return;
}
lua_getglobal(L, "setup");
if (lua_pcall(L, 0, 0, 0))
{
std::cout << "failed to call setup function" << std::endl;
return;
}
}
shared_ptr<myData> data;
};
void main()
{
myLua lua1("Apple");
myLua lua2("Orange");
}
绑定.h:
class Test
{
public:
void callHello(lua_State *L) {
//------------Added----------------
myLua::myData *b = static_cast<myLua::myData *>(lua_touserdata(L, -1));
cout << "RESULT2 : " << b->name << endl;
//---------------------------------
lua_getglobal(L, "hello");
lua_pushstring(L, "ClassName");
if (lua_pcall(L, 1, 0, 0))
{
std::cout << "failed to call hello function" << std::endl;
return;
}
};
};
bindings.i :(用于使用 SWIG 绑定 bindings.h)
%module my
%{
#include "bindings.h"
%}
%include <stl.i>
%include <std_string.i>
%include <std_vector.i>
%include <std_map.i>
%include <typemaps.i>
%typemap(default) (lua_State *L)
{
$1 = L;
}
typedef std::string string;
%include "bindings.h"
当前结果:
hello is called by : ClassName
hello is called by : ClassName
我想要的结果:
hello is called by : Apple
hello is called by : Orange
也许我可以以某种方式将变量注册到lua_State*?
如果有类似的东西我觉得会很棒
lua_registerdata(L, &name);
然后用类似的东西得到它
string name = lua_getregistereddata(L);
添加代码的结果:
RESULT1 : Apple
RESULT2 : \360n\240\300`\255\276\255\336\336\300ݺ\220\300`DD\255\276\255\336\336\300ݺ\300\217\300`\340_\300`D\376
hello is called by : ClassName
RESULT1 : Orange
RESULT2 : \360n\300`\255\276\255\336\336\300ݺ\200\236\300`DD\255\276\255\336\336\300ݺ@\236\300``w\300`D\376
hello is called by : ClassName
【问题讨论】:
-
如果你每次都创建一个新状态,只需将
name变量推送到全局表中。lua_pushstring(L, "orange"); lua_setglobal(L, "g_contextName")。那么 callHello 就是lua_getglobal(L, "hello"); lua_getglobal(L, "g_contextName"); if (lua_pcall(L, 1, 0, 0)) -
@JamesPoag 谢谢,但是如果
name变量不是字符串而是其他类型,例如结构指针呢? -
a的范围/生命周期是多少?a是否超出范围?&a是否仍指向有效内存?data更好,因为它是在堆上分配的。具体来说,您可以使用data.get()来获取原始指针。请记住,它不是引用计数。 -
即
lua_pushlightuserdata(&L, data.get()),然后检查指针值是否与您稍后使用lua_touserdata检索的值相同 -
你能更新你的例子吗?我无法想象 Lua 堆栈顶部仍然有 lightuserdata。这就是为什么我建议将 lightuserdata 存储在全局表 (
setglobal) 中。