2013-03-25 10 views
9

escript를 직접 작성하면 nif를 사용할 수 있지만 철근 배근 escriptize를 사용하면 nif 함수를 찾을 수 없습니다. 나는 * .so 객체가 빔 파일처럼 압축되지 않기 때문이라고 생각합니다. 다음은 간단한 예입니다.철근 철근 escriptize & nifs

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. 

철근은 escriptize
./test

를 컴파일 할 수-deps 결과는

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 
입니다

이를 극복 할 방법이 있습니까?

+0

오류로 인해 '* .so'가 아니라'jiffy.beam'이 발견되었습니다. 어쩌면'escriptize'는'ebin'의 의존성을 무시한'ebin'의 빔만을 고려했을지도 모릅니다. –

+0

@ Ed'ka, 아니요. nif가 아닌 종속성을 추가하면 안됩니다. 제대로 작동합니다. – cashmere

+0

그러나'jiffy.so'를'priv'에서 제거한 상태에서'jiffy : decode/1'을 호출하려고하면'undefined function'이 아니라'NIF library를로드하지 못했습니다 .'라는 오류 메시지가 나타납니다. –

답변

3

문제는 erlang:load_nif/1 기능 암시 .so 파일을 찾기 위해 노력하고 스마트 아무것도 할 모든 검색 경로를 사용하지 않습니다. 그냥 파일 이름 인수에 주어진대로 문자 그대로 파일을로드하려고합니다. 절대 파일 이름이 아닌 경우 현재 작업 디렉토리를 기준으로 파일을로드하려고 시도합니다. 로드 할 내용을 정확히으로로드합니다.

erlang:load_nif("jiffy.so")을 호출하면 현재 작업 디렉토리에서 "jiffy.so"을로드하려고 시도합니다.

load_nifs() -> 
    case os:getenv("NIF_DIR") of 
     false -> Path = "."; 
     Path -> Path 
    end, 
    ok = erlang:load_nif(Path ++ "/gpio_nifs", 0). 

이 쉽게 파일을 찾기 위해 검색 경로 아래로 루프를 확장 할 수 있습니다 : 내가 사용하고 그 주위에 간단한 작업은 NIF_DIR 환경 변수를 사용하여 같은 것을 할 것입니다. NIF_DIR은 특별한 이름이 아니며 "발명"한 것입니다.

+0

jiffy 코드를 편집했지만 도움이되지 않았습니다. 이것은 @lastcanal이 제안한 것과 유사합니다. .so를 올바른 위치로 복사하는 대신 재귀 적으로 찾습니다. 나는이 문제가 로딩과 관련이 없다고 생각한다.Ed'ka가 지적했듯이 정의되지 않은 함수 인 jiffy가 있습니다 : decode/1. – cashmere

+0

예,하지만'jiffy : decode/1'가 정의 된 부분은 언급되지 않았습니다. .so 파일에 있다면 파일이로드되지 않은 이유가있을 수 있습니다. 또는 전혀 정의되지 않았습니다. – rvirding

+0

[여기] (https://github.com/davisp/jiffy/blob/master/src/jiffy.erl#L10)에 정의되어 있습니다. 그리고 그것은 실제 nif 함수에 대한 호출을합니다. 정의되어 있고 코드 경로에서 erlang을 주어야합니다 : nif_error right? – cashmere

1

erlang:load_nif이 아카이브를 조사하지 않기 때문에 escript에서 nif를로드 할 수없는 것 같습니다. 대부분의 운영 체제에서는 메모리에 매핑 할 수있는 *.so의 실제 복사본이 필요하기 때문입니다.

이 문제를 극복하는 가장 좋은 방법은 * .so 파일을 escript의 출력 디렉토리에 복사하는 것입니다.

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

edis에 대한 escript builder를 살펴 보자. escript에서 실행을 위해 eleveldb의 nif를로드하는 방법을 알 수 있습니다.

+0

edis 코드는 [rebar code] (https://github.com/rebar/rebar/blob/master/src/rebar_escripter.erl#L69)와 매우 유사합니다. 나는'jiffy.so'를 escript와 같은 디렉토리에 복사하려했지만 도움이되지 못했습니다. – cashmere