有時我們想要在 Erlang 運(yùn)行時系統(tǒng)中運(yùn)行一個外語程序。在這種情況下,程序被編寫為一個共享庫,動態(tài)鏈接到 Erlang 運(yùn)行時系統(tǒng)。在程序員看來,鏈接驅(qū)動程序是一個端口程序,并且遵循與端口程序完全相同的協(xié)議。
創(chuàng)建鏈接驅(qū)動程序是與 Erlang 接口外語代碼的最有效方法,但也是最危險的方法。鏈接驅(qū)動程序中的任何致命錯誤都會導(dǎo)致 Erlang 系統(tǒng)崩潰。
以下是在Erlang中實(shí)現(xiàn)驅(qū)動程序的示例-
-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, Result} -> Result end. LINKED-IN DRIVERS 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.
請注意,使用驅(qū)動程序極為復(fù)雜,在使用驅(qū)動程序時應(yīng)格外小心。