-module(drv). -compile(export_all). % test api -define(SERVER, ?MODULE). start(Path) -> gen_server:start({local, ?SERVER}, ?MODULE, Path, []). test_call(Msg) -> gen_server:call(?SERVER, {test, self(), Msg}). % gen_server callbacks -record(state, {port}). init(Path) -> process_flag(trap_exit, true), OpenPort = fun() -> case catch open_port({spawn, drv}, [binary]) of Port when is_port(Port) -> {ok, #state{port = Port}}; Error -> {stop, Error} end end, case erl_ddll:load_driver(Path, "drv") of ok -> OpenPort(); {error, already_loaded} -> OpenPort(); Other -> {stop, Other} end. handle_call(Msg, From, State = #state{port = Port}) when is_port(Port) -> port_command(Port, term_to_binary({From, Msg})), {noreply, State}; handle_call(_Msg, _From, State) -> {reply, ok, State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info({Port, {data, Bin}}, State) when is_port(Port), is_binary(Bin) -> case binary_to_term(Bin) of {data, To, Msg} -> gen_server:reply(To, {data, Msg}); Other -> io:format("test> unknown reply: ~p~n", [Other]) end, {noreply, State}; handle_info(Msg, State) -> io:format("test> other message: ~p~n", [Msg]), {noreply, State}. terminate(_Reason, #state{port = Port}) when is_port(Port) -> port_close(Port), ok; terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. % end of gen_server callbacks t() -> start("."), Ret1 = (catch test_call("lalala")), io:format("~nret1: '~p'~n", [Ret1]), Ret2 = (catch test_call("pipipi")), io:format("~nret2: '~p'~n", [Ret2]).