如何在Lua中包装一个C库:我如何创建嵌套的函数表?
与此问题相关的代码在这里:https://github.com/jchester/lua-polarssl/tree/master/src
目前,我正在尝试包装PolarSSL库的一部分(http://polarssl.org),以便我可以访问SHA-512 HMACs(luacrypto不提供此功能)。
我希望的API的形式为:
a_sha512_hash = polarssl.hash.sha512('text')
或者更完整地写为:
local polarssl = require 'polarssl'
local hash = polarssl.hash
a_sha512_hash = hash.sha512('test')
如果你参考上面链接中的 polarssl.c,你会看到我已经编写了包装 PolarSSL 代码的函数。然后我试图构建函数表,如下所示:
LUA_API int luaopen_polarssl( lua_State *L ) {
static const struct luaL_Reg core[] = {
{ NULL, NULL }
};
static const struct luaL_Reg hash_functions[] = {
{ "sha512", hash_sha512 },
{ "sha384", hash_sha384 },
{ NULL, NULL }
};
static const struct luaL_Reg hmac_functions[] = {
{ "sha512", hmac_sha512 },
{ "sha384", hmac_sha384 },
{ NULL, NULL }
};
luaL_register( L, CORE_MOD_NAME, core );
luaL_register( L, HASH_MOD_NAME, hash_functions );
luaL_register( L, HMAC_MOD_NAME, hmac_functions );
return 1;
}
其中 CORE_MOD_NAME = 'polarssl',HASH_MOD_NAME = 'polarssl.hash',HMAC_MOD_NAME = 'polarssl.hmac'。
当我运行类似于本问题顶部的Lua代码的测试脚本时,我得到以下结果:
lua: test.lua:23: attempt to index global 'polarssl' (a nil value)
stack traceback:
test.lua:23: in main chunk
[C]: ?
我尝试寻找实现这种模块.子模块方法的示例(例如 naim vs luasockets),但似乎每个人都有不同的实现方式。我完全迷失了。
原文链接 https://stackoverflow.com/questions/9527417
虽然与问题不直接相关,但以下陈述并不完全正确:
目前我正在尝试包装 PolarSSL 库 (http://polarssl.org),以便我可以访问 SHA-512 HMAC(luacrypto 不提供此功能)。
我不知道您所指的 LuaCrypto 版本是哪个,但是此 LuaCrypto 分支 确实提供了 SHA-512 HMACs,还自动支持 OpenSSL 支持的任何其他摘要类型。只需将 "sha512"
作为摘要类型传递给 hmac.digest
:
hmac.digest("sha512", message, key)
文档仅说明了支持的部分摘要类型,完整列表可以通过调用 crypto.list("digests")
来检索。
table.foreach(crypto.list("digests"), print)
想想看,即使是原始的 LuaCrypto 应该也支持 SHA-512。
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
那就是 Lua,每个人都有自己的方式。这是 Lua 的最大优点和最大弱点:语言提供机制,而不是 _策略_。
你需要做的第一件事就是停止使用
luaL_register
。是的,我知道它很方便。但你想要特别的东西,而luaL_register
无法帮助你获得它。你所想要的是创建一个包含一个或多个函数的表。所以 …… 就这么做吧。
创建一个表。
很容易。该函数将一个表推送到堆栈上,所以我们的堆栈现在有一个表在其顶部。这是我们将要返回的表。
现在,我们需要创建一个新表来放在旧表里。
同样很容易。接下来,我们要把要放入该表中的函数推入堆栈。
所以堆栈有三个东西:目标表,"哈希"表(我们将在下文中"命名"它),以及我们想要放进 "哈希"表中的函数。
那么就把这个函数放入哈希表中吧。
lua_setfield(L, -2, "sha512");
这会将堆栈上最顶部的东西取出,并将其设置为名为 "sha512" 的字段,该字段所在的是堆栈上从-2开始的表。这就是我们的"哈希"表。该函数完成后,它会从堆栈上移除顶部项目。这将把我们的"哈希"表放在顶部。
我们可以重复第二个函数的这个过程:
lua_pushcfunction(L, hash_sha384); lua_setfield(L, -2, "sha384");
现在,我们想将"哈希"表放入要返回的表中。这可以通过另一个
lua_setfield
调用轻松完成:lua_setfield(L, -2, "hash");
记住:这个函数将_任何_在堆栈顶部的东西取走。此时,我们要返回的表(也将是我们的模块表)位于堆栈上。
我们可以为"hmac"表重复此过程:
lua_newtable(L); //创建"hmac"表 lua_pushcfunction(L, hmac_sha512); lua_setfield(L, -2, "sha512"); lua_pushcfunction(L, hmac_sha384); lua_setfield(L, -2, "sha384"); lua_setfield(L, -2, "hmac"); //将"hmac"表放入我们的模块表中
该模块表现在有两个条目:"哈希"和"hmac"。两者都是具有两个函数的表。
我们可以用以下代码将其放入全局表中:
lua_pushvalue(L, -1); lua_setfield(L, LUA_GLOBALSINDEX, "polarssl");
并非每个模块制作者都想这样做。有些人更喜欢强制使用
local polarssl = require "polarssl"
语法,以避免污染全局命名空间。这取决于你。但无论如何,你必须_返回_此表。从你的
luaopen
函数中返回 1,以让 Lua 知道有一个返回值。上述的lua_pushvalue
调用仅用于复制表(记住:表是引用的,因此就像复制指针一样)。这样,当你使用lua_setfield
时,副本就从堆栈中被移除,而原始的表仍然可以用作返回值。