【问题标题】:lua newbie : C-Lua How to pass a struct/buffer to lua from C?lua 新手:C-Lua 如何将结构/缓冲区从 C 传递给 lua?
【发布时间】:2020-10-03 19:43:12
【问题描述】:

我遵循了这个样板示例:http://www.matrix44.net/blog/?p=456

我能够从 C 向 Lua 发送字符串,但是当我传递一个结构时出现错误(我使用了 lua_newuserdata)。

C 剪辑

//s = (ST*) malloc ( sizeof(ST) );
//    lua_pushlightuserdata(state, s);
s = lua_newuserdata(state, sizeof(ST));
s->a=11;
s->b=12;
printf ( "s = %p \n", s ); // Prints 0x80a708
result = lua_pcall(state, 0, LUA_MULTRET, 0);

Lua 剪辑

print(foo)  -->  Prints 0x80a708
io.write("received has:\n", foo.a); --> ERROR : Failed to run script: script.lua:1: attempt to index global 'foo' (a userdata value)

如何将缓冲区转换为结构/表记录?

最终,我的 C 程序不知道结构体,它只会将缓冲区传递给 Lua,而 Lua 知道结构体并需要在那里转换。

谢谢, PS:脚本和C程序的printf都匹配(0x80a708),我可以投吗??

【问题讨论】:

  • 除了赋值和相等测试外,Lua 中没有对userdata 值的预定义操作。您必须使用用户数据的元表来定义查找的工作方式。 ...另外,如果您的 C 程序不知道结构,但 Lua 知道 - 它来自哪里?
  • 基本上,C 程序是一个代理,它传递给 Lua [假设它是一个知道 struc 类型的客户端] 服务器发送的这个缓冲区。
  • 问题是,使用任何方法,您在 C 中得到的只是字符串形式的成员名称(使用表或带有__index 元方法的用户数据)。我不知道如何仅通过将结构的名称包含在字符串中来返回结构的成员-除非您创建某种将这些字符串映射到成员/偏移量的表(或switch 语句)-您将不得不明确地这样做,而你必须知道结构的成员。
  • 已解决:我使用了 luajit,并且能够传递一个缓冲区并将其转换为 lua 端的 C 结构。

标签: lua


【解决方案1】:

Lua 没有结构,它有表。

Userdata 是一种将不透明数据传递给 Lua 的便捷方式,但 Lua 无法看到内部数据。用户数据只有在你将它传递回 C++ 并且你有办法确定它是什么时才有用(本质上是将它转换为正确的类型)。

Lua 表最接近 C++ 中的结构。你可以这样写:

lua_newtable(state);
lua_pushnumber(state, s->a);
lua_setfield(state, -2, "a");
lua_pushnumber(state, s->b);
lua_setfield(state, -2, "b");

有了这个,现在就可以在lua中引用了:

print(foo.a); -- this will now print 11

【讨论】:

  • 我知道表格。我的 C 程序不知道结构它只是一个将缓冲区传递给 lua 的代理,那么我如何将该缓冲区转换为 lua 结构或表?我仍在阅读索引,但不明白。
  • 在某些时候,您需要 C 来了解缓冲区的结构。 Lua 本身无法做到这一点,因为 C 结构只是一堆指向指针的偏移量,并且由编译器生成。访问 C 结构的唯一安全方法是通过 C。如果在构造时没有表示,则可以创建一个元表并将其附加到您最初使用的用户数据。然后,为元表实现 __index 以返回适当的值。您必须在 C 中执行此操作。查看此内容以了解如何使用元表来索引值:lua.org/pil/13.4.1.html
  • @purpletech 或者,如果您最需要 Lua 来理解结构,您可以将其视为两端的 Lua 表。这样,您将拥有一个 LuaTable 类,而不是原生 C 结构,该类具有 GetField(或 GetNumber,如果您不使用模板)等方法。
【解决方案2】:

Lua 代码无法访问用户数据内部结构。
使用表将结构从 C 传递到 Lua。
或者通过 metatable 为您的用户数据手动定义索引。

【讨论】:

    【解决方案3】:

    已解决:我使用了 luajit,并且能够传递一个缓冲区并将其转换为 lua 端的 C 结构。

    【讨论】:

    • 你用什么做的? cdata = ffi.cast(ct, init) 或 ctype = ffi.metatype(ct, metatable) ?谢谢
    猜你喜欢
    • 1970-01-01
    • 2013-07-24
    • 2011-11-10
    • 2012-11-08
    • 2012-05-27
    • 1970-01-01
    • 1970-01-01
    • 2015-03-13
    • 2011-01-14
    相关资源
    最近更新 更多