2013-03-25 10 views
9

posso usare di NIF se scrivo l'Escript me stesso, però quando uso tondo per cemento armato escriptize le funzioni NIF non può essere trovato. Penso che sia perché gli oggetti * .so non vengono impacchettati come file di travi. Ecco un semplice esempio;erlang tondo per cemento armato escriptize & NIF

rebar.config:

{deps, [ 
    {'jiffy', "", {git, "https://github.com/davisp/jiffy.git", {branch, master}}} 
]}. 
{escript_incl_apps, [jiffy]}. 
%% I tried this to see what happens if the so got in there but didn't help 
{escript_incl_extra, [{"deps/jiffy/priv/jiffy.so", "/path/to/my/proj"}]}. 

test.erl:

-module(test). 

-export([main/1]). 

main(_Args) -> 
    jiffy:decode(<<"1">>), 
    ok. 

tondo per cemento armato get-deps compilare escriptize
./test

e il risultato è

escript: exception error: undefined function jiffy:decode/1 
    in function test:main/1 (src/test.erl, line 7) 
    in call from escript:run/2 (escript.erl, line 741) 
    in call from escript:start/1 (escript.erl, line 277) 
    in call from init:start_it/1 
    in call from init:start_em/1 

Esiste un modo per superare questo?

+0

Da l'errore sembra che è 'jiffy.beam' che non può essere trovato, non' * .so'. Forse 'escriptize' prende in considerazione solo i raggi di' ebin' che ignorano le dipendenze ''ebin's? –

+0

@ Ed'ka, no se aggiungi una dipendenza che non è un nif, funziona perfettamente. – cashmere

+0

Ma se provate a chiamare 'jiffy: decode/1' con' jiffy.so' rimosso da 'priv' dovreste ottenere l'errore' Impossibile caricare la libreria NIF', non 'funzione indefinita' –

risposta

3

Il problema è che la funzione erlang:load_nif/1 fa non implicitamente utilizzare alcun percorso di ricerca fare nulla intelligente nel tentativo di trovare il file .so. Cerca semplicemente di caricare il file letteralmente come indicato dall'argomento del nome del file. Se non è un nome di file assoluto, tenterà di caricare il file relativo alla directory di lavoro corrente. Si carica esattamente cosa si dice di carico.

Quindi se si chiama erlang:load_nif("jiffy.so") allora proverà a caricare "jiffy.so" dalla directory di lavoro corrente. Un semplice lavoro in giro che ho usato è quello di fare qualcosa di simile, che utilizza la variabile NIF_DIR ambiente:

load_nifs() -> 
    case os:getenv("NIF_DIR") of 
     false -> Path = "."; 
     Path -> Path 
    end, 
    ok = erlang:load_nif(Path ++ "/gpio_nifs", 0). 

Questo può facilmente essere esteso a ciclo lungo un percorso di ricerca per trovare il file. Si noti che NIF_DIR non è un nome speciale, solo uno che ho "inventato".

+0

Ho modificato il codice jiffy per farlo ma non mi ha aiutato. Questo è simile a quanto suggerito da @lastcanal. Invece di copiare su .so per correggere il luogo, lo cerchi ricorsivamente. Penso che questo problema non sia relizzante al caricamento .so.Come ha sottolineato Ed'ka, dice la funzione non definita jiffy: decode/1. – cashmere

+0

Sì, ma non è mai stato specificato dove si doveva definire 'jiffy: decode/1'. Se si trovava nel file .so, un motivo poteva essere che il file non era mai stato caricato. O non definito affatto. – rvirding

+0

è definito [qui] (https://github.com/davisp/jiffy/blob/master/src/jiffy.erl#L10). E fa una chiamata alla funzione nif effettiva, se è stata definita correttamente definita e nel percorso del codice dovrebbe dare un erlang: nif_error giusto? – cashmere

1

Non sembra possibile caricare un NIF da un EScript perché erlang:load_nif non sembra in archivi. Questo perché la maggior parte dei sistemi operativi richiede una copia fisica di *.so che può essere mappata in memoria.

Il modo migliore per superare questo è copiando i * .so file nella directory di output del Escript.

{ok, _Bytes} = file:copy("deps/jiffy/priv/jiffy.so", "bin/jiffy.so"), 

Date un'occhiata al escript builder per edis. Vedrete che questo è il modo in cui caricano il nif di eleveldb per l'esecuzione da una copia.

+0

Il codice edis è molto simile a [codice dell'armatura] (https://github.com/rebar/rebar/blob/master/src/rebar_escripter.erl#L69). Ho provato a copiare 'jiffy.so' nella stessa directory con l'escript, ma non ha aiutato. – cashmere