c - 在 Lua 中与嵌套函数一起使用 C 变量

标签 c variables lua nested

这是我之前关于嵌套注册 C 函数的问题的后续: Trying to call a function in Lua with nested tables

上一个问题给了我添加嵌套函数的答案,如下所示:

dog.beagle.fetch()

我也希望在该级别有变量,例如:

dog.beagle.name
dog.beagle.microchipID

我希望这个字符串和数字在 C 中分配并可由 Lua 访问。因此,在 C 代码中,变量可以定义为:

int microchipIDNumber;
char dogname[500];

C 变量需要通过 Lua 中的赋值来更新,当其值位于等号右侧时,需要由 Lua 检索它的值。我已经尝试过 __index 和 __newindex 元方法概念,但是当我在变量的 Lua 路径中有 2 个点时,我尝试的一切似乎都会崩溃。我知道我可能用两个点让它变得更复杂,但是它使 Lua 代码的组织更容易阅读。我还需要获取分配事件,因为当 microchipIDNumber 值发生变化时,我需要启动一些硬件。我假设我可以在设置值时通过 __newindex 来完成此操作。

关于如何编写元表和方法来完成嵌套有什么想法吗?难道是因为我之前的函数声明让Lua混淆了?

最佳答案

Lua 中的冒号运算符( : )仅用于函数。考虑以下示例:

meta = {}
meta["__index"] = function(n,m) print(n) print(m) return m end
object = {}
setmetatable(object,meta)
print(object.foo)

索引函数将简单地打印它传递的两个参数并返回第二个参数(我们也将打印它,因为仅执行 object.foo 是一个语法错误)。输出将是 table: 0x153e6d0 foo foo与新线路。所以__index获取我们在其中查找变量的对象及其名称。现在,如果我们替换 object.fooobject:foo我们得到这个:

input:5: function arguments expected near ')'

这是因为:object:fooobject.foo(object) 的语法糖,因此 Lua 希望您为函数调用提供参数。如果我们确实提供了参数( object:foo("bar") ),我们会得到:

table: 0x222b3b0
foo
input:5: attempt to call method 'foo' (a string value)

所以我们的 __index函数仍然被调用,但它没有传递参数 - Lua 只是尝试调用返回值。所以不要使用:对于成员(member)。

抛开这些,让我们看看如何在 Lua 和 C 之间同步变量。这实际上非常复杂,并且有不同的方法可以实现。一种解决方案是使用 __index 的组合和__newindex 。如果您有beagle对于 C 中的结构,我建议创建这些 C 函数并将它们作为 C 闭包推送到 Lua 表的元表中,并使用指向 C 结构的指针作为上值。看this有关 lua_pushcclosure 的一些信息和 this一般而言,关于 Lua 中的闭包。

如果您没有可以引用的单个结构,它会变得更加复杂,因为您必须以某种方式存储对 variableName-variableLocation在 C 端并知道每个是什么类型。你可以在实际的Lua表中维护这样一个列表,所以 dog.beagle将是变量名称到一两个东西的映射。对于这个“东西”有几个选择。首先 - 一个轻量用户数据(即 - 一个 C 指针),但随后你会遇到弄清楚它指向什么的问题,以便你知道要推送什么 Lua 类型 __index以及要弹出什么__newindex 。另一种选择是推送两个函数/闭包。您可以为必须处理的每种类型(数字、字符串、表等)创建一个 C 函数,并为每个变量推送适当的函数,或者创建一个 uber-closure,它接受一个参数,然后给出它的类型只需改变你插入它的上值即可。在这种情况下 __index__newindex函数将简单地为给定的变量名查找适当的函数并调用它,因此在 Lua 中实现它可能是最简单的。

如果有两个函数,则 dog.beagle可能看起来像这样(不是实际的 Lua 语法):

dog.beagle = {
  __metatable = {
    __index = function(table,key)
      local getFunc = rawget(table,key).get
      return getFunc(table,key)
    end

    __newindex = function(table,key,value)
      local setFunc = rawget(table,key).set
      setFunc(table,key,value)
    end
  }
  "color" = {
    "set" = *C function for setting color or closure with an upvalue to tell it's given a color*,
    "get" = *C function for getting color or closure with an upvalue to tell it to return a color*
  }
}

以上注意事项: 1.不要设置对象的__metatable直接字段 - 它用于隐藏真正的元表。使用setmetatable(对象,元表)。 2. 注意 rawget 的用法。我们需要它,因为否则会尝试从 __index 中获取对象的字段将是无限递归。 3. 您必须在事件rawget(table,key)中进行更多的错误检查。返回nil ,或者如果它返回的内容没有 get/set成员。

关于c - 在 Lua 中与嵌套函数一起使用 C 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13499047/

相关文章:

使用不同的堆栈指针调用 C 函数 (gcc)

将 C 字符串转换为二进制值数组,然后逐位传输数组

java - 是否可以通过 set(...).value(...) 设置变量?

if-statement - 什么是更快?一个循环或多个 if 条件

machine-learning - 如何使用 nngraph 访问中间层的输出?

lua - 如何在neovim中获取当前的cmdline内容?

c - 从c中的函数返回一个float类型

c++ - `rand()` 的用处 - 或者谁应该调用 `srand()` ?

c++ - 每次调用方法时增加变量

excel - 具有日期条件的自动过滤器返回空白