11

自分で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 compile
escriptize ./test

結果は

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

これを克服する方法はありますか?

4

2 に答える 2

3

問題は、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これは特別な名前ではなく、私が「発明した」名前であることに注意してください。

于 2013-03-28T15:34:11.730 に答える
1

erlang:load_nifアーカイブを調べないため、escriptからnifをロードすることはできないようです。これは、ほとんどのオペレーティングシステムで、*.soメモリにマップできるの物理コピーが必要なためです。

これを克服する最良の方法は、*。soファイルをescriptの出力ディレクトリにコピーすることです。

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

のescriptビルダーを見てくださいedis。これが、escriptから実行するためにeleveldbのnifをロードする方法であることがわかります。

于 2013-03-27T19:36:41.103 に答える