【发布时间】:2019-02-13 23:30:12
【问题描述】:
我正在尝试从 C++ 中的 Lua 脚本(chunk A)中获取 userdata(通过我的示例中的函数返回的变量),然后,稍后将这个 userdata 传递回 Lua 脚本(@987654326 @) 来自 C++(在我的示例中通过函数参数),因此 userdata 可以在 chunk B 中使用,就像在 chunk A 中一样。
MyBindings.h
class Vec2
{
public:
Vec2():x(0), y(0){};
Vec2(float x, float y):x(x), y(y){};
float x, y;
};
MyBindings.i
%module my
%{
#include "MyBindings.h"
%}
%include "MyBindings.h"
main.cpp
#include <iostream>
#include <lua.hpp>
extern "C"
{
int luaopen_my(lua_State *L);
}
int main()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
luaopen_my(L);
lua_settop(L, 0);
/* chunk A */
luaL_dostring(L, "local vec2 = my.Vec2(3, 4)\n"
"function setup()\n"
"return vec2\n"
"end\n");
/* chunk B */
luaL_dostring(L, "function test(p)\n"
"print(p.x)\n"
"end\n");
void *userDataPtr = nullptr;
/* call setup function */
int top = lua_gettop(L);
lua_getglobal(L, "setup");
if (lua_pcall(L, 0, LUA_MULTRET, 0))
{
std::cout << lua_tostring(L, -1) << '\n';
lua_pop(L, 1);
}
/* check the return value */
if (lua_gettop(L) - top)
{
/* store userdata to a pointer */
if (lua_isuserdata(L, -1))
userDataPtr = lua_touserdata(L, -1);
}
/* check if userDataPtr is valid */
if (userDataPtr != nullptr)
{
/* call test function */
lua_getglobal(L, "test");
lua_pushlightuserdata(L, userDataPtr); /* pass userdata as an argument */
if (lua_pcall(L, 1, 0, 0))
{
std::cout << lua_tostring(L, -1) << '\n';
lua_pop(L, 1);
}
}
lua_close(L);
}
我得到的结果:
[string "local vec2 = my.Vec2(3, 4)..."]:6: 尝试索引 a 用户数据值(本地“p”)
我期望的结果:
3
是否可以从chunk A 获取userdata,然后将其传递给chunk B,以便可以像在chunk A 中一样使用它?
【问题讨论】:
-
哦,这是一个难题,因为 SWIG 引入了自己的抽象层来处理用户数据。如果这是在 SWIG 生成的库中,您可以使用 SWIG's Lua-C API,但在外部则非常棘手。
-
查看更新后的答案。
-
Lua DLL 可以动态加载。也许我不明白 swig,但 DLL 应该是一个单独的构建目标。我假设
luaopen_my(L);仅用于测试目的。lua_getglobal(L, "require"); lua_pushlstring(L, file, strlen(file));后跟lua_pcall(L, 1, 0, 0);就是您需要做的所有事情。见这里github.com/tilkinsc/LuaConsole/blob/…
标签: c++ lua swig lua-userdata