English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Erlang Drivers

Sometimes we want to run a foreign program in the Erlang runtime system. In this case, the program is written as a shared library and dynamically linked to the Erlang runtime system. To the programmer, the linked driver is a port program and follows the same protocol as port programs.

Creating a driver

Creating a linked driver is the most effective but also the most dangerous method of interfacing foreign code with Erlang. Any fatal error in the linked driver can cause the Erlang system to crash.

The following is an example of implementing a driver in Erlang.-

Example

-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.

Please note that using drivers is extremely complex, and extra caution should be exercised when using drivers.