如何将复杂的cdata结构巧妙地转换成灵活多变的lua字符串?

2026-04-01 20:281阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计629个文字,预计阅读时间需要3分钟。

如何将复杂的cdata结构巧妙地转换成灵活多变的lua字符串?

我正在编写一个需要在LuaJit中读取复杂二进制消息的小应用程序。尽管我直接使用了bit模块和string.rep,但这整个过程非常繁琐。作为一名LuaJit的新手,我认为使用FFI可能会有更简单的方法。

我正在编写一个需要在LuaJit中读取一些复杂二进制消息的小应用程序.

我一直在使用bit模块和string.rep.然而,这一切都非常麻烦.我是使用LuaJit的新手,并认为使用FFI可能会有更简单的方法.

在C中我可以声明这样的结构:

struct mystruct { uint32_t field1; char field2[6]; uin64_t field3; short field4; } __attribute__(packed);

在阅读LuaJit的FFI时,你似乎可以宣布

ffi.cdef[[ #pragma pack(1) struct mystruct { uint32_t field1; char field2[6]; uin64_t field3; short field4; }; ]]

然后我可以创建一个mystruct并访问这样的字段:

local ms = ffi.new("mystruct") ms.field1 = 32; // ... etc

但是,如何将其转换为lua字符串?

我尝试了这个,但它似乎没有做我想要的.

local s = tostring(ms)

还有这个:

如何将复杂的cdata结构巧妙地转换成灵活多变的lua字符串?

local s = ffi.string(ms)

产生以下错误“错误的参数#1到’字符串'(不能将’struct mystruct’转换为’const char *’)”

所以我试了一个演员:

local s = ffi.string(ffi.cast("char*", ms))

没有错误,但它在电线上看起来不对.

ffi.string与非类似字符串的参数一起使用时,必须明确指定长度:

str = ffi.string(ptr [,len])

Creates an interned Lua string from the data pointed to by ptr.

If the optional argument len is missing, ptr is converted to a “char *” and the data is assumed to be zero-terminated. The length of the string is computed with strlen().

运行以下代码时,我得到了预期的(小端)结果:

ffi = require 'ffi' ffi.cdef[[ typedef unsigned long uint32_t; typedef unsigned long long uint64_t; #pragma pack(1) struct mystruct { uint32_t field1; char field2[6]; uint64_t field3; short field4; }; ]] function string.tohex(str) return (str:gsub('.', function (c) return string.format('%02X', string.byte(c)) end)) end ms = ffi.new('struct mystruct', 1, {2, 3, 4, 5, 6, 7}, 8, 9) s = ffi.string(ms, ffi.sizeof(ms)) -- specify how long the byte sequence is print(s:tohex()) --> 01000000020304050607

str = ffi.string(ptr [,len])

Creates an interned Lua string from the data pointed to by ptr.

If the optional argument len is missing, ptr is converted to a "char *" and the data is assumed to be zero-terminated. The length of the string is computed with strlen().

000000000000900

更新:我知道这不是原始问题的一部分,但我刚刚学会了这个技巧,为了完成,这里有一种方法将Lua字符串转换回FFI cdata:

data = ffi.new('struct mystruct') -- create a new cdata ffi.copy(data, s, ffi.sizeof(data)) -- fill it with data from Lua string 's' print(data.field1, data.field4) --> 1 9

本文共计629个文字,预计阅读时间需要3分钟。

如何将复杂的cdata结构巧妙地转换成灵活多变的lua字符串?

我正在编写一个需要在LuaJit中读取复杂二进制消息的小应用程序。尽管我直接使用了bit模块和string.rep,但这整个过程非常繁琐。作为一名LuaJit的新手,我认为使用FFI可能会有更简单的方法。

我正在编写一个需要在LuaJit中读取一些复杂二进制消息的小应用程序.

我一直在使用bit模块和string.rep.然而,这一切都非常麻烦.我是使用LuaJit的新手,并认为使用FFI可能会有更简单的方法.

在C中我可以声明这样的结构:

struct mystruct { uint32_t field1; char field2[6]; uin64_t field3; short field4; } __attribute__(packed);

在阅读LuaJit的FFI时,你似乎可以宣布

ffi.cdef[[ #pragma pack(1) struct mystruct { uint32_t field1; char field2[6]; uin64_t field3; short field4; }; ]]

然后我可以创建一个mystruct并访问这样的字段:

local ms = ffi.new("mystruct") ms.field1 = 32; // ... etc

但是,如何将其转换为lua字符串?

我尝试了这个,但它似乎没有做我想要的.

local s = tostring(ms)

还有这个:

如何将复杂的cdata结构巧妙地转换成灵活多变的lua字符串?

local s = ffi.string(ms)

产生以下错误“错误的参数#1到’字符串'(不能将’struct mystruct’转换为’const char *’)”

所以我试了一个演员:

local s = ffi.string(ffi.cast("char*", ms))

没有错误,但它在电线上看起来不对.

ffi.string与非类似字符串的参数一起使用时,必须明确指定长度:

str = ffi.string(ptr [,len])

Creates an interned Lua string from the data pointed to by ptr.

If the optional argument len is missing, ptr is converted to a “char *” and the data is assumed to be zero-terminated. The length of the string is computed with strlen().

运行以下代码时,我得到了预期的(小端)结果:

ffi = require 'ffi' ffi.cdef[[ typedef unsigned long uint32_t; typedef unsigned long long uint64_t; #pragma pack(1) struct mystruct { uint32_t field1; char field2[6]; uint64_t field3; short field4; }; ]] function string.tohex(str) return (str:gsub('.', function (c) return string.format('%02X', string.byte(c)) end)) end ms = ffi.new('struct mystruct', 1, {2, 3, 4, 5, 6, 7}, 8, 9) s = ffi.string(ms, ffi.sizeof(ms)) -- specify how long the byte sequence is print(s:tohex()) --> 01000000020304050607

str = ffi.string(ptr [,len])

Creates an interned Lua string from the data pointed to by ptr.

If the optional argument len is missing, ptr is converted to a "char *" and the data is assumed to be zero-terminated. The length of the string is computed with strlen().

000000000000900

更新:我知道这不是原始问题的一部分,但我刚刚学会了这个技巧,为了完成,这里有一种方法将Lua字符串转换回FFI cdata:

data = ffi.new('struct mystruct') -- create a new cdata ffi.copy(data, s, ffi.sizeof(data)) -- fill it with data from Lua string 's' print(data.field1, data.field4) --> 1 9