繁体   English   中英

在Lua内部与嵌套函数一起使用C变量

[英]Using C variable inside Lua alongside nested functions

这是对我先前关于嵌套注册的C函数的先前问题的一种补充:在此处找到: 使用嵌套表在Lua中调用函数

上一个问题为我提供了添加如下嵌套函数的答案:

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)

index函数将只打印它传递的两个参数,然后返回第二个参数(我们也将打印该参数,因为仅执行object.foo是语法错误)。 输出将是table: 0x153e6d0 foo foo和新行。 因此, __index获得了我们要在其中查找变量的对象及其名称。 现在,如果我们用object:foo替换object.foo ,我们将得到:

input:5: function arguments expected near ')'

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

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

因此我们的__index函数仍然被调用,但是没有传递参数-Lua只是尝试调用返回值。 因此,请勿对成员使用:

顺便说一句,让我们看一下如何在Lua和C之间同步变量。这实际上是相当复杂的,并且有不同的方法来实现。 一种解决方案是结合使用__index__newindex 如果您在C语言中拥有beagle结构,则建议您使用这些C函数并将它们作为C闭包推入Lua表的元表中,并以指向C结构的指针作为上值。 看看对一些信息lua_pushcclosure这个总体上关闭在Lua。

如果您没有可以引用的单一结构,则它将变得更加复杂,因为您必须以某种方式在C端存储对variableName-variableLocation ,并知道每种类型是什么。 您可以在实际的Lua表中维护这样的列表,因此dog.beagle将是变量名到一两个变量的映射。 对于这种“东西”有几种选择。 首先-一个简单的用户数据(即-C指针),但是接下来您将要弄清楚指向的内容,这样您就知道要为__index推送的Lua类型以及为__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直接设置对象的__metatable字段-它用于隐藏真正的元表。 使用setmetatable(object,metaable)。 2.注意rawget的用法。 我们需要它,因为否则尝试从__index内获取对象的字段将是无限递归。 3.如果rawget(table,key)返回nil ,或者返回的内容没有get / set成员,则必须进行一些错误检查。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM