2012-03-02 3 views
11

код связан с этим вопросом здесь: https://github.com/jchester/lua-polarssl/tree/master/srcОбтекание библиотеки C для Lua: как создать вложенные таблицы функций?

В настоящее время я пытаюсь обернуть одну часть библиотеки 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 в ссылке выше, вы увидите I 'написанные функции, которые завершают код 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 против luasockets), но у всех, кажется, есть другой способ его достижения. Я полностью потерян.

+0

Я не могу ссылаться на naim и luasockets, потому что я нажимаю <10-точечный лимит на ссылки. –

+0

Похож, что карма раздается как восхитительные лотосы, поэтому обновленная почта со ссылками. –

ответ

14

У каждого, кажется, есть другой способ его достижения.

Это Lua; каждый делает это по-своему. Это наибольшая сила и наибольшая слабость Lua: язык предоставляет механизмы, а не политики .

Первое, что вам нужно сделать, это остановиться, используя luaL_register. Да, я знаю, что это удобно. Но вы хотите что-то особенное, и luaL_register не поможет вам это получить.

Вы хотите создать таблицу, содержащую таблицу, содержащую одну или несколько функций. Итак ... сделайте это.

Создать таблицу.

lua_newtable(L); 

Это было легко. Функция подталкивает таблицу к стеку, поэтому наш стек теперь имеет таблицу поверх нее. Это та таблица, которую мы вернем.

Теперь нам нужно создать новую таблицу, чтобы войти в старую.

lua_newtable(L); 

Снова, легко. Затем мы хотим поместить функцию, которую хотим включить в эту таблицу в стеке.

lua_pushcfunction(L, hash_sha512); 

Так стек имеет три вещи: таблицы назначения, «хэш» таблицы (мы доберемся до «назвать» его в секунду), а функция, которую мы хотим поместить в «хэш» Таблица.

Поэтому помещаем функцию в хэш-таблицу.

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); //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 

Столик модуля теперь имеет две записи в нем: «хэш» и «HMAC». Оба являются таблицами с двумя функциями в них.

Мы можем вставить его в глобальную таблицу с этим:

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

Не каждый модуль производитель хочет сделать это. Некоторые предпочитают принуждать людей использовать синтаксис local polarssl = require "polarssl", чтобы избежать загрязнения глобального пространства имен. Тебе решать.

Но что вы должны делать в любом случае, это return Эта таблица. Верните 1 из вашей функции luaopen, чтобы Lua знал, что есть одно возвращаемое значение. Вышеописанный вызов lua_pushvalue существует с единственной целью копирования таблицы (помните: на таблицы ссылаются, так что это похоже на копирование указателя). Таким образом, когда вы используете lua_setfield, копия удаляется из стека, а оригинал остается в качестве возвращаемого значения.

+0

Thankyou. Сначала я был немного озадачен, но наброски движений стека на бумаге помогли мне уловить процесс. –

+3

+1 за то, что вы столкнулись с некоторыми проблемами, чтобы обсудить возвращаемое значение с 'require' ... многие люди, похоже, не знают, что рекомендуемая практика изменилась с« просто привяжите ваш модуль к глобальному », чтобы« вернуть » ваш модуль из require, и вызывающий должен поместить его в локальную переменную « – snogglethorpe

2

Не напрямую связана с вопросом, но следующее утверждение не совсем верно:

В настоящее время я пытаюсь обернуть одну часть библиотеки PolarSSL (http://polarssl.org), чтобы дать мне доступ к SHA-512 HMAC (luacrypto не предоставляет этого).

Я не знаю, какую версию LuaCrypto вы имеете в виду, но this LuaCrypto fork не предусматривает SHA-512 HMACs, а также любой другой тип, поддерживаемый OpenSSL автоматически переваривать. Просто передайте "sha512" как тип дайджеста:

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

В документации указывается только часть поддерживаемых типов дайджеста, полный список можно получить с помощью вызова crypto.list("digests").

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

Когда я думаю об этом, даже оригинальный LuaCrypto должен поддерживать SHA-512.

+0

Спасибо, я не знал об этом. Тем не менее, я убегал от «основной» вилки, которая не обертывает SHA512. Я решил обернуть PolarSSL, потому что он мал, и API очень прост - каждый модуль является автономным и может быть скомпилирован независимо. Например, я собрал только модуль SHA512/384. Общий размер: 22kb. –

+0

Это действительно очень разумный размер! Выглядит отлично, если вы хотите встроить Lua с криптографическими возможностями. –

Смежные вопросы