[英]erlang rebar escriptize & nifs
如果我自己編寫escript,我可以使用nif,但是當我使用rebar escriptize時,無法找到nif函數。 我認為這是因為* .so對象沒有像束文件那樣被打包。 這是一個簡單的例子;
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.
rebar get-deps編譯escriptize
。/測試
結果是
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
有辦法克服這個問題嗎?
問題是,在erlang:load_nif/1
功能不會隱式使用任何搜索路徑,也沒有做任何事情,試圖找到聰明.so
文件。 它只是嘗試按文件名參數的字面加載文件。 如果它不是絕對文件名,那么它將嘗試相對於當前工作目錄加載文件。 它正好加載你要它加載的內容。
因此,如果你調用erlang:load_nif("jiffy.so")
那么它將嘗試從你當前的工作目錄加載"jiffy.so"
。 我使用的一個簡單的工作是使用NIF_DIR
環境變量做這樣的事情:
load_nifs() ->
case os:getenv("NIF_DIR") of
false -> Path = ".";
Path -> Path
end,
ok = erlang:load_nif(Path ++ "/gpio_nifs", 0).
這可以很容易地擴展到循環搜索路徑以查找文件。 請注意, NIF_DIR
不是一個特殊名稱,只是我“發明”的名稱。
似乎無法從escript加載nif,因為erlang:load_nif
不會查看存檔。 這是因為大多數操作系統都需要可以映射到內存的*.so
的物理副本。
解決此問題的最佳方法是將* .so文件復制到escript的輸出目錄中。
{ok, _Bytes} = file:copy("deps/jiffy/priv/jiffy.so", "bin/jiffy.so"),
看看在escript建設者為edis
。 您將看到這是他們如何從escript加載eleveldb的nif執行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.