2012-03-02 12 views
11

Il codice relativo a questa domanda è qui: https://github.com/jchester/lua-polarssl/tree/master/srcDisposizione di una libreria C per Lua: come si creano tabelle di funzioni nidificate?

Attualmente sto cercando di avvolgere una parte della libreria PolarSSL (http://polarssl.org) per darmi l'accesso a SHA-512 HMAC (luacrypto fa non fornire questo).

L'API che sto puntando è della forma:

a_sha512_hash = polarssl.hash.sha512('text') 

o più pienamente

local polarssl = require 'polarssl' 
local hash = polarssl.hash 

a_sha512_hash = hash.sha512('test') 

Se si fa riferimento al polarssl.c nel link qui sopra, vedrete I Ho scritto funzioni che avvolgono il codice PolarSSL. Poi sto cercando di costruire le tabelle di funzione così:

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; 
} 

Dove CORE_MOD_NAME = 'polarssl', HASH_MOD_NAME = 'polarssl.hash', HMAC_MOD_NAME = 'polarssl.hmac'.

Quando eseguo uno script di test simile al codice Lua nella parte superiore di questa domanda, ottengo questo:

lua: test.lua:23: attempt to index global 'polarssl' (a nil value) 
stack traceback: 
    test.lua:23: in main chunk 
    [C]: ? 

Ho provato a cercare esempi di come raggiungere questo approccio module.submodule (es. naim vs luasockets), ma tutti sembrano avere un modo diverso di raggiungerlo. Sono completamente perso.

+0

Non riesco a collegarmi a naim e luasockets perché ho raggiunto il limite <10 punti sui collegamenti. –

+0

Sembra che il karma venga distribuito come deliziosi lecca lecca, quindi post aggiornato con link. –

risposta

14

tutti sembrano avere un modo diverso di raggiungerlo.

Questo è Lua; ognuno fa a modo suo. È la più grande forza e la più grande debolezza di Lua: il linguaggio fornisce meccanismi, non politiche.

La prima cosa che devi fare è smettere di usare luaL_register. Sì, lo so che è conveniente. Ma vuoi qualcosa di speciale, e luaL_register non ti aiuterà a farlo.

Quello che vuoi è creare una tabella che contenga una tabella che contenga una o più funzioni. Quindi ... fallo.

Creare un tavolo.

lua_newtable(L); 

È stato facile. La funzione spinge un tavolo in pila, quindi il nostro stack ora ha una tabella su di esso. Questo è il tavolo che torneremo.

Ora, abbiamo bisogno di creare una nuova tabella per entrare in quella vecchia.

lua_newtable(L); 

Ancora, facile. Quindi, vogliamo mettere la funzione che vogliamo andare in quella tabella in pila.

lua_pushcfunction(L, hash_sha512); 

Così la pila ha tre cose: la tabella di destinazione, la tabella "hash" (ci arriveremo a "denominazione" in un secondo), e la funzione vogliamo mettere in "hash" tavolo.

Quindi inserire la funzione nella tabella hash.

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

Questo richiede tutto ciò che è in cima alla pila e lo imposta nel campo denominato "sha512" sul tavolo al -2 indice sulla pila. Ecco dove si trova il nostro tavolo "hash". Al termine di questa funzione, rimuove l'elemento superiore dalla pila. Questo lascia il tavolo "hash" in alto.

Siamo in grado di ripetere il processo per la seconda funzione:

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

Ora, vogliamo mettere la tabella "hash" nella tabella vogliamo tornare. Questo è fatto abbastanza facilmente con un altro lua_setfield chiamata:

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

Ricorda: questa funzione prende qualunque è in cima alla pila. A questo punto, la tabella che vogliamo tornare (che sarà la tabella del nostro modulo) è in pila.

Possiamo ripetere questo processo per la tavola "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 

tavolo del modulo ha ora due voci in essa: "hash" e "hmac". Entrambe sono tabelle con due funzioni in esse.

possiamo infilarla nella tabella globale con questo:

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

Non tutti i moduli produttore vuole fare questo. Alcuni preferiscono forzare le persone ad usare la sintassi local polarssl = require "polarssl", per evitare di inquinare lo spazio dei nomi globale. Tocca a voi.

Ma quello che devi fare in entrambi i casi è quello di restituire questa tabella. Restituisci 1 dalla tua funzione luaopen, per far sapere a Lua che esiste un valore di ritorno. La chiamata lua_pushvalue sopra esiste al solo scopo di copiare la tabella (ricorda: le tabelle sono referenziate, quindi è come copiare un puntatore). In questo modo, quando si utilizza lua_setfield, la copia viene rimossa dallo stack, mentre l'originale rimane da utilizzare come valore di ritorno.

+0

Grazie. All'inizio ero un po 'perplesso, ma abbozzare i movimenti dello stack sulla carta mi ha aiutato a seguire il processo. –

+3

+1 per avere qualche problema a discutere del valore restituito da 'require' ... molte persone non sembrano essere consapevoli del fatto che la pratica raccomandata si è spostata da" solo attaccare il modulo in un globale "a" ritorno il tuo modulo da richiedere, e il chiamante dovrebbe metterlo in una variabile locale " – snogglethorpe

2

non direttamente collegate alla domanda, ma la seguente affermazione non è del tutto vero:

Attualmente sto cercando di avvolgere una parte della libreria PolarSSL (http://polarssl.org) per dare accesso a SHA-512 HMACs (luacrypto non fornisce questo).

Non so quale versione di LuaCrypto ti riferisci, ma this LuaCrypto fork FORNISCE SHA-512 HMAC, e anche qualsiasi altro tipo supportato da OpenSSL automaticamente digerire. Basta passare "sha512" come tipo di digerire:

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

La documentazione solo una parte dei tipi di digerire supportati, l'elenco completo può essere recuperato chiamando crypto.list("digests").

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

Quando ci penso, anche LuaCrypto originale dovrebbe supportare SHA-512.

+0

Grazie, non ne ero a conoscenza. Tuttavia, stavo scappando dalla forcella "principale" che non avvolge SHA512. Ho scelto di avvolgere PolarSSL perché è piccolo e l'API è molto semplice - ogni modulo è autonomo e può essere compilato in modo indipendente. Ad esempio, ho compilato solo il modulo SHA512/384. Dimensione totale: 22kb. –

+0

Questa è davvero una dimensione molto ragionevole! Sembra fantastico se vuoi incorporare Lua con funzionalità crittografiche. –

Problemi correlati