English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Иногда мы хотим запускать иностранный программный код в системе выполнения Erlang. В этом случае программа пишется в виде общей библиотеки и динамически подключается к системе выполнения Erlang. С точки зрения программиста, связанный драйвер является портовым приложением и следует тем же протоколом, что и портовые приложения.
Создание связанного драйвера — это наиболее эффективный, но и наиболее опасный способ взаимодействия с иностранным кодом через интерфейс Erlang. Любая критическая ошибка в связанном драйвере может привести к аварийному завершению работы системы Erlang.
Следующий пример показывает реализацию драйвера в Erlang.
-module(helloworld). -export([start/0, stop/0]). -export([twice/1, sum/2]). start() -> start("example1_drv"). start(SharedLib) -> case erl_ddll:load_driver(".", SharedLib) of ok -> ok; {error, already_loaded} -> ok; _ -> exit({error, could_not_load_driver}) end, spawn(fun() -> init(SharedLib) end). init(SharedLib) -> register(example1_lid, self()), Port = open_port({spawn, SharedLib}, []), loop(Port). stop() -> example1_lid ! stop. twice(X) -> call_port({twice, X}). sum(X, Y) -> call_port({sum, X, Y}). call_port(Msg) -> example1_lid ! {call, self(), Msg}, receive {example1_lid, Результат} -> Результат end. ЛИНКЕД-ИН ДРАЙВЕРА 223 loop(Port) -> receive {call, Caller, Msg} -> Port ! {self(), {command, encode(Msg)}}, receive {Port, {data, Data}} -> Caller ! {example1_lid, decode(Data)} end, loop(Port); stop -> Port ! {self(), close}, receive {Port, closed} -> exit(normal) end; {'EXIT', Port, Reason} -> io:format("~p ~n", [Reason]), exit(port_terminated) end. encode({twice, X}) -> [1, X]; encode({sum, X, Y}) -> [2, X, Y]. decode([Int]) -> Int.
Обратите внимание, что использование драйверов очень сложно, и при использовании драйверов следует быть особенно внимательным.