将C Integer绑定到Lua全局变量

时间:2016-01-13 07:38:16

标签: c lua

在C中,我想调用一个使用全局变量x的lua函数myFunction()。我希望能够直接将c(整数)变量注册为此全局变量x。

有些事情:

demo.lua:

function myFunction()
  return x + 3
end

demo.c:

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

2 个答案:

答案 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中的全局变量...)