二郎钢筋和NIFS escriptize(erlang rebar escriptize & nif

2019-08-18 00:04发布

当我用螺纹钢escriptize的NIF功能不​​能发现我可以用NIF的,如果我写的escript自己,但是。 我想这是因为*。所以对象没有得到挤得像束文件。 下面是一个简单的例子;

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.

螺纹钢得到-的DEP编译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

有没有办法解决这个?

Answer 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不是一个特别的名字,只有一个我“发明”。



Answer 2:

这似乎并不可能从escript加载NIF因为erlang:load_nif不考虑存档。 这是因为大多数操作系统需要的物理副本*.so ,可以被映射到内存中。

要克服这一点的最好办法是由* .so文件复制到escript的输出目录。

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

看看在escript建设者为edis 。 你会看到这是如何加载eleveldb的NIF用于从escript执行。



文章来源: erlang rebar escriptize & nifs