在C中,我想调用一个使用全局变量x的lua函数myFunction()。我希望能够直接将c(整数)变量注册为此全局变量x。
有些事情:
function myFunction()
return x + 3
end
int x = 0;
lua_bindglob(L, "x", &x);
for (x = 0; x < 100; ++x)
{
lua_getglobal(L, "myFunction");
// here I call the function and it should evaluate
// to the current value of x (in c)
lua_pcall(L, 0, 1, 0);
int result = lua_tonumber(L, -1);
lua_pop(L, 1);
}
我知道我可以通过这个来修改lua全局变量:
lua_pushnumber(L, 3);
lua_setglobal(L, "x");
但我需要更直接/更快的方式来做到这一点。我得到了一个提示,LUA ligthuserdata可能会有帮助,但我找不到任何关于普通变量的例子。
编辑: 由于我从基准测试中得到表达式,所以我不想改变它们: 请参阅示例here:
答案 0 :(得分:2)
你能得到的最好的是能够创建一个用户数据(常规,而不是轻量),它具有__call
元方法,可以为你获得/设置C值。 / p>
所以你的功能看起来像是:
function myFunction()
return x() + 3
end
它还可以定义运算符元方法,以便像x + 3
这样的东西可以工作。但裸体x
没有办法解析你想要的值。
设置值如下所示:
x(3)
没有办法像x = 3
那样以你想要的方式工作。这将始终覆盖有问题的值。
使用__newindex
和__index
元方法不起作用,因为您希望变量全局。
或者,您可以使用LuaJIT及其FFI接口。
答案 1 :(得分:2)
如果您只想从Lua访问几个C变量,可以在globals表上设置一个带有__index
和__newindex
元方法的元表。当访问(获取或设置)不存在的全局变量时,会调用这些元方法,并且您必须通过查看这些元方法的第二个参数(变量名称)来确定要执行的操作。
导出单个变量的模块的示例代码:
#include <string.h>
#include <limits.h>
#include <lua.h>
#include <lauxlib.h>
static int x = 0;
static int myvar_index( lua_State* L ) {
char const* key = lua_tostring( L, 2 );
if( key != NULL && strcmp( key, "x" ) == 0 )
lua_pushinteger( L, x );
else
lua_pushnil( L );
return 1;
}
static int myvar_newindex( lua_State* L ) {
char const* key = lua_tostring( L, 2 );
if( key != NULL && strcmp( key, "x" ) == 0 ) {
lua_Integer i = luaL_checkinteger( L, 3 );
if( i > INT_MAX || i < INT_MIN )
luaL_error( L, "variable value out of range" );
x = i;
} else
lua_rawset( L, 1 );
return 0;
}
int luaopen_myvar( lua_State* L ) {
luaL_Reg const metamethods[] = {
{ "__index", myvar_index },
{ "__newindex", myvar_newindex },
{ NULL, NULL }
};
#if LUA_VERSION_NUM < 502
lua_pushvalue( L, LUA_GLOBALSINDEX );
lua_newtable( L );
luaL_register( L, NULL, metamethods );
#else
lua_pushglobaltable( L );
luaL_newlib( L, metamethods );
#endif
lua_setmetatable( L, -2 );
return 0;
}
您导出的C变量越多,元方法实现就越复杂,您可能最好使用其他一种建议的方法。
另请注意,globals表是一个共享资源,因此您必须避免/处理与修改其metatable的其他代码的冲突。 (即可重用模块根本不应该修改共享资源 - 但我想这同样适用于C中的全局变量...)