C++ Lua从C函数返回自定义数据
尽管搜索很困难,但我找不到一个有效的LuaC API示例,用于调用从C函数返回自定义数据的Lua函数。 例如,我有一个注册函数“GetMyVector”,然后我从lua调用它来从C检索信息,我得到的是一个表,但我想要的是类似于从C中的结构访问access变量的东西,例如:C++ Lua从C函数返回自定义数据,c++,c,lua,luabind,C++,C,Lua,Luabind,尽管搜索很困难,但我找不到一个有效的LuaC API示例,用于调用从C函数返回自定义数据的Lua函数。 例如,我有一个注册函数“GetMyVector”,然后我从lua调用它来从C检索信息,我得到的是一个表,但我想要的是类似于从C中的结构访问access变量的东西,例如: local x = GetMyVector() print(x[1]) -- i print(x[2]) -- j print(x[3]) -- k -- how to access it via like this: pr
local x = GetMyVector()
print(x[1]) -- i
print(x[2]) -- j
print(x[3]) -- k
-- how to access it via like this:
print(x.i)
print(x.j)
print(x.k)
my C函数通过lua_pushnumber在三维数组中推送向量:
static int GetMyVector(lua_State *L)
{
vec3_t vec;
vec[0] = 1;
vec[1] = 2;
vec[3] = 3;
lua_newtable(L);
lua_pushnumber(L, vec[0]);
lua_rawseti(L, -2, 1);
lua_pushnumber(L, vec[1]);
lua_rawseti(L, -2, 2);
lua_pushnumber(L, vec[2]);
lua_rawseti(L, -2, 3);
return 1;
}
你可能想要。它允许为表格设置任何键。如果键是文本,则可以通过x[“i”]
或x.i
获取数据。
代码应该类似于
static int GetMyVector(lua_State *L)
{
vec3_t vec;
vec[0] = 1;
vec[1] = 2;
vec[3] = 3;
lua_newtable(L);
lua_pushliteral(L, "i");
lua_pushnumber(L, vec[0]);
lua_settable(L, -2);
lua_pushliteral(L, "j");
lua_pushnumber(L, vec[1]);
lua_settable(L, -2);
lua_pushliteral(L, "k");
lua_pushnumber(L, vec[2]);
lua_settable(L, -2);
return 1;
}
它有一点扩展,但由于@geov,我找到了我想要的东西,它有点类似于C#中的属性样式。我想,解决方案如下:
#define MYCLASSNAME "vec"
typedef struct {
int i, j, k;
} MyVec_t;
typedef int(*Xet_func) (lua_State *L, void *v);
/* member info for get and set handlers */
typedef const struct{
const char *name; /* member name */
Xet_func func; /* get or set function for type of member */
size_t offset; /* offset of member within MyVec_t */
} Xet_reg_pre;
typedef Xet_reg_pre * Xet_reg;
// properties
static int Get_Int(lua_State *L, void *v) {
lua_pushnumber(L, *(int*)v);
return 1;
}
static int Set_Int(lua_State *L, void *v) {
*(int*)v = luaL_checkinteger(L, 3);
return 0;
}
static int Get_Number(lua_State *L, void *v) {
lua_pushnumber(L, *(lua_Number*)v);
return 1;
}
static int Set_Number(lua_State *L, void *v) {
*(lua_Number*)v = luaL_checknumber(L, 3);
return 0;
}
static int Get_String(lua_State *L, void *v) {
lua_pushstring(L, (char*)v);
return 1;
}
static void Property_Add(lua_State *L, Xet_reg l)
{
for (; l->name; l++) {
lua_pushstring(L, l->name);
lua_pushlightuserdata(L, (void*)l);
lua_settable(L, -3);
}
}
static int Property_Call(lua_State *L)
{
Xet_reg m = (Xet_reg)lua_touserdata(L, -1);
lua_pop(L, 1);
luaL_checktype(L, 1, LUA_TUSERDATA);
return m->func(L, (void *)((char *)lua_touserdata(L, 1) + m->offset));
}
static int index_handler(lua_State *L)
{
/* stack has userdata, index */
lua_pushvalue(L, 2); /* dup index */
lua_rawget(L, lua_upvalueindex(1)); /* lookup member by name */
if (!lua_islightuserdata(L, -1)) {
lua_pop(L, 1); /* drop value */
lua_pushvalue(L, 2); /* dup index */
lua_gettable(L, lua_upvalueindex(2)); /* else try methods */
if (lua_isnil(L, -1)) /* invalid member */
luaL_error(L, "cannot get member '%s'", lua_tostring(L, 2));
return 1;
}
return Property_Call(L); /* call get function */
}
static int newindex_handler(lua_State *L)
{
/* stack has userdata, index, value */
lua_pushvalue(L, 2); /* dup index */
lua_rawget(L, lua_upvalueindex(1)); /* lookup member by name */
if (!lua_islightuserdata(L, -1)) /* invalid member */
luaL_error(L, "cannot set member '%s'", lua_tostring(L, 2));
return Property_Call(L); /* call set function */
}
static MyVec_t *CheckMyVec(lua_State *L, int index) // get data
{
MyVec_t *p;
luaL_checktype(L, index, LUA_TUSERDATA);
p = (MyVec_t *)luaL_checkudata(L, index, MYCLASSNAME);
return p;
}
static MyVec_t *PushMyVec(lua_State *L) // push data
{
MyVec_t *p = (MyVec_t *)lua_newuserdata(L, sizeof(MyVec_t));
luaL_getmetatable(L, MYCLASSNAME);
lua_setmetatable(L, -2);
return p;
}
static int MyVec_Create(lua_State *L) // C function which will push data
{
MyVec_t *p;
p = PushMyVec(L);
p->i = luaL_checkinteger(L, 1);
p->j = luaL_checkinteger(L, 2);;
p->k = luaL_checkinteger(L, 3);;
return 1;
}
static int MyVec_destroy(lua_State *L)
{
MyVec_t *p = (MyVec_t *)lua_touserdata(L, 1);
return 0;
}
static int MyVec_Position(lua_State *L)
{
MyVec_t *p = CheckMyVec(L, 1);
double x = p->i;
double y = p->j;
double z = p->k;
if (lua_gettop(L) > 1) {
p->i = luaL_checknumber(L, 2);
p->j = luaL_checknumber(L, 3);
p->k = luaL_checknumber(L, 4);
}
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, z);
return 2;
}
static const luaL_Reg myvec_meta_methods[] = {
{ "__gc", MyVec_destroy },
{ 0, 0 }
};
static const luaL_Reg myvec_methods[] = {
{ "create", MyVec_Create },
{ "position", MyVec_Position },
{ 0, 0 }
};
static const Xet_reg_pre MyVec_get[] = {
{ "i", Get_Int, offsetof(MyVec_t, i) },
{ "j", Get_Int, offsetof(MyVec_t, j) },
{ "k", Get_Int, offsetof(MyVec_t, k) },
{ 0, 0 }
};
static const Xet_reg_pre MyVec_set[] = {
{ "i", Set_Int, offsetof(MyVec_t, i) },
{ "j", Set_Int, offsetof(MyVec_t, j) },
{ "k", Set_Int, offsetof(MyVec_t, k) },
{ 0, 0 }
};
int MyVec_Register(lua_State *L)
{
int metatable, methods;
/* create methods table, & add it to the table of globals */
luaL_openlib(L, MYCLASSNAME, myvec_methods, 0);
methods = lua_gettop(L);
/* create metatable for MyVec_t, & add it to the registry */
luaL_newmetatable(L, MYCLASSNAME);
luaL_openlib(L, 0, myvec_meta_methods, 0); /* fill metatable */
metatable = lua_gettop(L);
lua_pushliteral(L, "__metatable");
lua_pushvalue(L, methods); /* dup methods table*/
lua_rawset(L, metatable); /* hide metatable:
metatable.__metatable = methods */
lua_pushliteral(L, "__index");
lua_pushvalue(L, metatable); /* upvalue index 1 */
Property_Add(L, MyVec_get); /* fill metatable with getters */
lua_pushvalue(L, methods); /* upvalue index 2 */
lua_pushcclosure(L, index_handler, 2);
lua_rawset(L, metatable); /* metatable.__index = index_handler */
lua_pushliteral(L, "__newindex");
lua_newtable(L); /* table for members you can set */
Property_Add(L, MyVec_set); /* fill with setters */
lua_pushcclosure(L, newindex_handler, 1);
lua_rawset(L, metatable); /* metatable.__newindex = newindex_handler */
lua_pop(L, 1); /* drop metatable */
return 1; /* return methods on the stack */
}
“如果您有任何关于这方面的教程和信息,请将lnk粘贴到下面,我将不胜感激。”要求我们推荐或查找书籍、工具、软件库、教程或其他非现场资源的问题因堆栈溢出而脱离主题,因为它们往往会吸引固执己见的答案和垃圾邮件。相反,请描述问题以及迄今为止为解决问题所做的工作。是的,我设法解决了这个问题,但老实说,我不知道该怎么做,因为我也不知道该如何命名,也找不到任何关于这方面的信息来采取一点措施并解决这个问题。