2013-03-25 15 views
9

Esnafı kendim yazıyorsam, nif kullanabiliyorum, ancak inşaat demiri kullandığım zaman nif işlevleri bulunamıyor. Sanırım, çünkü * .so nesneleri kiriş dosyaları gibi paketlenmiyor. İşte basit bir örnek;erlang rebar escriptize & nifs

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. 

inşaat demiri escriptize
./test

derlemek get-Deps ve sonuç

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 
olduğunu

Bunun üstesinden gelmenin bir yolu var mı?

+0

Hatadan, '* .so' değil, bulunamayan' jiffy.beam 'gibi görünüyor. Belki 'eskortize' sadece 'ebin' bağımlılıklarını görmezden gelen ışınları hesaba katar 'ebin? –

+0

@ Ed'ka, nif olmayan bir bağımlılık eklerseniz, iyi çalışır. – cashmere

+0

Ama eğer jiffy: decode/1 ile jiffy.so'yu 'priv' kaldırılırsa 'denmeye çalışırsanız,' NIF kitaplığı yüklenemedi' hatası, 'undefined function' değil, –

cevap

3

sorun erlang:load_nif/1 fonksiyon dolaylı ne de.so dosyayı bulmak için çalışırken akıllı bir şey yapmak herhangi bir arama yolunu kullanmaz yapmasıdır. Dosyayı tam olarak dosya adı argümanı ile verildiği gibi yüklemeye çalışır. Mutlak bir dosya adı değilse, dosyayı geçerli çalışma dizinine göre yüklemeye çalışır. Yüklemek için ne anlattığınız tam olarak yükler.

erlang:load_nif("jiffy.so") numaralı telefonu arayarak, "jiffy.so" geçerli çalışma dizininizden yüklenmeye çalışacaktır.

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

Bu kolayca dosyayı bulmak için bir arama yolu aşağı döngü uzatılabilir: ben kullandım o etrafında basit bir iş NIF_DIR ortam değişkeni olarak kullanan böyle bir şey yapmaktır. NIF_DIR'un özel bir isim olmadığını, yalnızca "icat ettiğim" olduğunu unutmayın.

+0

Bunu yapmak için jiffy kodunu düzenledim ama yardımcı olmadım. Bu, @lastcanal'ın önerdiği şeye benzer. Yerine kopyalamak için .so yerine, yinelemeli olarak ararsınız. Bence bu sorun yükleme ile ilgili değil.Ed'ka'nın işaret ettiği gibi, tanımlanmamış bir işlev jiffy: decode/1. – cashmere

+0

Evet, ama asla 'jiffy: decode/1' tanımlanması gereken yerde belirtilmedi. Eğer .so dosyasında olsaydı, dosya hiçbir zaman yüklenmemiş olabilirdi. Ya da hiç tanımlanmamış. – rvirding

+0

tanımlanmıştır [burada] (https://github.com/davisp/jiffy/blob/master/src/jiffy.erl#L10). Ve doğru bir şekilde tanımlanmış ve kod yolunda bir erlang: nif_error vermesi gerekiyorsa, gerçek nif işlevine bir çağrı yapar? – cashmere

1

erlang:load_nif arşivlere bakmadığı için bir nif dosyasını bir formadan yüklemek mümkün görünmüyor. Bunun nedeni çoğu işletim sisteminin belleğe eşlenebilecek *.so fiziksel kopyasını gerektirmesidir.

Bunu aşmanın en iyi yolu, * .so dosyalarını eskinin çıktı dizinine kopyalamaktır.

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

edis için escript builder bir göz atın. Bunu göreceksiniz ki, eleveldb'nin nifini bir eskorttan yürütme için nasıl yüklediklerini göreceksiniz.

+0

edis kodu, [rebar code] 'a çok benzemektedir (https://github.com/rebar/rebar/blob/master/src/rebar_escripter.erl#L69). Esnaf ile aynı dizine 'jiffy.so' kopyalamayı denedim ama yardımcı olmadı. – cashmere