2015-04-27 17 views
8

Ciao Sto cercando di ottenere il Ciao Mondo esempio per Erlang NIF (Native funzione implementata) mostrato qui http://www.erlang.org/doc/man/erl_nif.html lavorare da Elixir su OSX a 64 bit.Elixir NIF- Ciao Mondo esempio su x64 di Mac OSX

prima cosa creare il codice C:

/* niftest.c */ 
#include "erl_nif.h" 

static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) 
{ 
    return enif_make_string(env, "Hello world!", ERL_NIF_LATIN1); 
} 

static ErlNifFunc nif_funcs[] = 
{ 
    {"hello", 0, hello} 
}; 

ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL) 

Poi ho compilare correttamente utilizzando gcc per l'architettura a 64 bit come suggerito qui Erlang NIF Test -- OS X Lion

gcc -undefined dynamic_lookup -dynamiclib niftest.c -o niftest.so -I /usr/local/Cellar/erlang/R14B02/lib/erlang/usr/include 

che produce il file necessario niftest.so che ho dovrebbe essere in grado di collegarsi da Erlang/Elixir. My Elixir (niftest.ex) si presenta così (ispirato ad un esempio più complesso riportato here):

defmodule Niftest do 
@onload :init 
    def init() do 
    :erlang.load_nif("./niftest", 0) 
    :ok 
    end 

    def hello() do 
    "NIF library not loaded" 
    end 

end 

Ora con niftest.so e niftest.ex nella stessa directory ho fuoco fino elisir utilizzando iex e digitare Niftest.hello e tutto quello che torno è: "Libreria NIF non caricata"

Mi manca un passaggio fondamentale? - per favore aiuto!

risposta

11

Il carico della libreria non riesce in modo silenzioso. Si può affermare che ci riesce usando:

:ok = :erlang.load_nif("./niftest", 0) 

Ciò si traduce in un errore:

** (MatchError) no match of right hand side value: 
{:error, {:bad_lib, 'Library module name \'niftest\' does not match calling module \'\'Elixir.Niftest\'\''}} 
niftest.ex:4: Niftest.init/0 

Questo accade perché un lib NIF può essere chiamato solo dal suo modulo "possedere". Il nome di quel modulo è il primo argomento al ERL_NIF_INIT macro, in modo da poter risolvere il problema modificando quella chiamata e ricompilando:

ERL_NIF_INIT(Elixir.Niftest,nif_funcs,NULL,NULL,NULL,NULL) 

C'è anche un errore di battitura nel gancio di carico. Dovrebbe essere:

@on_load :init 
+0

Hai ragione - la tua sarà la risposta accettata - molte grazie! – GavinBrelstaff

+0

Si scopre che la direttiva @onload: init non funziona come previsto, quindi devo chiamare manualmente Niftest.init prima di chiamare Nifteast.hello. Non so perché. – GavinBrelstaff

+3

'@ onload' non funziona perché dovrebbe essere' @ on_load'. Aggiornamento della risposta –