10

与这个问题相关的代码在这里:https ://github.com/jchester/lua-polarssl/tree/master/src

目前我正在尝试包装 PolarSSL 库 (http://polarssl.org) 的一部分,以便让我访问 SHA-512 HMAC(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]: ?

我尝试寻找如何实现这种 module.submodule 方法的示例(例如naim vs luasockets),但每个人似乎都有不同的实现方式。我完全迷路了。

4

2 回答 2

15

每个人似乎都有不同的实现方式。

那是Lua;每个人都以自己的方式做事。这是 Lua 最大的优势和最大的弱点:语言提供机制,而不是策略

您需要做的第一件事是停止使用luaL_register. 是的,我知道这很方便。但是您想要一些特别的东西,并且luaL_register不会帮助您获得它。

您想要的是创建一个表,其中包含一个包含一个或多个函数的表。所以……这样做。

创建一个表。

lua_newtable(L);

那很简单。该函数将一个表压入堆栈,因此我们的堆栈现在在其顶部有一个表。这是我们将返回的表格。

现在,我们需要创建一个新表进入旧表。

lua_newtable(L);

再次,简单。接下来,我们要将要进入该表的函数放入堆栈中。

lua_pushcfunction(L, hash_sha512);

所以堆栈有三样东西:目标表、“散列”表(我们稍后会“命名”它),以及我们想要放入“散列”表的函数。

所以将函数放入哈希表中。

lua_setfield(L, -2, "sha512");

这将获取堆栈顶部的任何内容并将其设置到堆栈上 -2 索引处的表上名为“sha512”的字段中。这就是我们的“哈希”表所在的位置。此函数完成后,它会从堆栈中删除顶部项目。这将“哈希”表留在顶部。

我们可以对第二个函数重复这个过程:

lua_pushcfunction(L, hash_sha384);
lua_setfield(L, -2, "sha384");

现在,我们要将“散列”表放入我们要返回的表中。lua_setfield另一个电话很容易做到这一点:

lua_setfield(L, -2, "hash");

请记住:此函数获取堆栈顶部的任何内容。此时,我们要返回的表(将是我们模块的表)在堆栈上。

我们可以对“hmac”表重复这个过程:

lua_newtable(L); //Create "hmac" table
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"); //Put the "hmac" table into our module table

该模块的表中现在有两个条目:“hash”和“hmac”。两者都是具有两个功能的表。

我们可以将其粘贴到全局表中:

lua_pushvalue(L, -1);
lua_setfield(L, LUA_GLOBALSINDEX, "polarssl");

并非每个模块制造商都想这样做。有些人更喜欢强迫人们使用local polarssl = require "polarssl"语法,以避免污染全局命名空间。由你决定。

但是,无论哪种方式,您都必须返回此表。从你的函数中返回 1 luaopen,让 Lua 知道有一个返回值。上面的lua_pushvalue调用存在的唯一目的是复制表(记住:表被引用,所以它就像复制一个指针)。这样,当您使用 时lua_setfield,副本将从堆栈中删除,而原始副本仍用作返回值。

于 2012-03-02T04:17:33.037 回答
2

与问题没有直接关系,但以下陈述并不完全正确:

目前我正在尝试包装 PolarSSL 库 (http://polarssl.org) 的一部分,以便让我访问 SHA-512 HMAC(luacrypto 不提供此功能)。

我不知道你指的是哪个版本的 LuaCrypto,但这个 LuaCrypto 分支确实提供了 SHA-512 HMAC,以及 OpenSSL 自动支持的任何其他摘要类型。只需"sha512"作为摘要类型传递:

hmac.digest("sha512", message, key)

文档只说明了支持的摘要类型的一部分,完整的列表可以通过调用来检索crypto.list("digests")

table.foreach(crypto.list("digests"), print)

当我想到它时,即使是原始的 LuaCrypto 也应该支持 SHA-512。

于 2012-03-02T18:07:15.513 回答