簡體   English   中英

erlang rebar escriptize&nifs

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM