繁体   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