The driver_entry structure is a C struct that all erlang
drivers defines. It contains entry points for the erlang driver
that are called by the erlang emulator when erlang code accesses
the driver.
All functions are function pointers. The driver_init
function returns a pointer to the driver_entry
structure. The name in the structure must correspond to the name
of the driver, and the driver library file name (without file
extension).
The erl_driver driver API functions needs a port handle
that identifies the driver instance (and the port in the
emulator). This is only passed to the start function, but
not to the other functions. The start function returns a
driver-defined handle that is passed to the other functions. A
common practice is to have the start function allocating
some application-defined structure and stash the port
handle in it, to use it later with the driver API functions.
The driver call-back functions are called synchronously from the erlang emulator. If they take too long before completing, they can cause timeouts in the emulator. Use the queue or asynchronous calls if nessecary, since the emulator must be responsive.
This is called directly after the driver has been loaded by
erl_ddll:load_driver/2. (Actually when the driver is
added to the driver list.) The driver should return 0, or if
the driver can't initialize, -1.
int start(ErlDrvPort port, char* command)
This is called when the driver is instantiated, when
open_port/2 is called. The driver should return a
number >= 0 or a pointer, or if the driver can't be started,
one of three error codes should be returned:
ERL_DRV_ERROR_GENERAL - general error, no error code
ERL_DRV_ERROR_ERRNO - error with error code in erl_errno
ERL_DRV_ERROR_BADARG - error, badarg
If an error code is returned, the port isn't started.
void stop(ErlDrvData drv_data)
This is called when the port is closed, with
port_close/1 or Port ! {self(), close}. Note
that terminating the port owner process also closes the
port.
void output(ErlDrvData drv_data, char *buf, int len)
This is called when an erlang process has sent data to the
port. The data is pointed to by buf, and is
len bytes. Data is sent to the port with Port !
{self(), {command, Data}}, or with
port_command/2. Depending on how the port was opened,
it should be either a list of integers 0...255 or a
binary. See open_port/3 and port_command/2.
void ready_input(ErlDrvData drv_data, ErlDrvEvent event)
void ready_output(ErlDrvData drv_data, ErlDrvEvent event)
This is called when a driver event (given in the
event parameter) is signaled. This is used to help
asynchronous drivers "wake up" when something happens.
On unix the event is a pipe or socket handle (or
something that the select system call understands).
On Windows the event is an Event or Semaphore (or
something that the WaitForMultipleObjects API
function understands). (Some trickery in the emulator allows
more than the built-in limit of 64 Events to be used.)
To use this with threads and asynchronous routines, create a
pipe on unix and an Event on Windows. When the routine
completes, write to the pipe (use SetEvent on
Windows), this will make the emulator call
ready_input or ready_output.
This is the name of the driver, it must correspond to the
atom used in open_port, and the name of the driver
library file (without the extension).
This function is called by the erl_ddll driver when the
driver is unloaded. (It is only called in dynamic drivers.)
The driver is only unloaded as a result of calling
unload_driver/1, or when the emulator halts.
This field is not used, it's still around only for historical
reasons. It should be NULL. Don't use it.
int control(ErlDrvData drv_data, unsigned int command, char *buf,
int len, char **rbuf, int rlen)
This is a special routine invoked with the erlang function
port_control/3. It works a little like an "ioctl" for
erlang drivers. The data given to port_control/3
arrives in buf and len. The driver may send
data back as a driver binary, using *rbuf and
rlen.
This is the fastest way of calling a driver and get a response. It won't make any context switch in the erlang emulator, and requires no message passing. It is suitable for calling C function to get faster execution, when erlang is too slow.
If the driver wants to return data, it should return it in
rbuf. When control is called, rbuf
points to a pointer to a buffer of rlen bytes, which
can be used to return data. Data is returned depending of
the port control flags (those that are set with set_port_control_flags).
If the flag is set to PORT_CONTROL_FLAG_BINARY, then
rbuf should point to a driver binary or be NULL.
Note that this binary must be freed. If rbuf is set to
NULL, an empty list will be returned.
If the flag is set to 0,
rbuf points to a char* containing data,
that is returned as a list of integers. Using binaries is
faster if more than a few bytes are returned.
The return value is the number of bytes returned in
*rbuf.
void timeout(ErlDrvData drv_data)
This function is called any time after the driver's timer
reaches 0. The timer is activeated with
driver_set_timer. There are no priorities or ordering
among drivers, so if several drivers time out at the same
time, any one of them is called first.
void outputv(ErlDrvData drv_data, ErlIOVec *ev)
This function is called whenever the port is written to. If
it is NULL, the output function is called
instead. This function is faster than output, because
it takes an ErlIOVec directly, which requires no
copying of the data. The port should be in binary mode, see
open_port/2.
The ErlIOVec contains both a SysIOVec,
suitable for writev, and one or more binaries. If
these binaries should be retained, when the driver returns
from outputv, they can be queued (using driver_enq_bin
for instance), or if they are kept in a static or global
variable, the reference counter can be incremented.
void ready_async(ErlDrvData drv_data, ErlDrvThreadData
thread_data)
This function is called after an asynchronous call has completed. The asynchronous call is started with driver_async. This function is called from the erlang emulator thread, as opposed to the asynchronous function, which is called in some thread (if multithreading is enabled).
This function is called from erlang:port_call/3. It
works a lot like the control call-back, but uses the
external term format for input and output.
command is an integer, obtained from the call from
erlang (the second argument to erlang:port_call/3).
buf and len provide the arguments to the call
(the third argument to erlang:port_call/3). They can
be decoded using ei functions.
rbuf points to a return buffer, rlen bytes
long. The return data should be a valid erlang term in the
external (binary) format. This is converted to an erlang
term and returned by erlang:port_call/3 to the
caller. If more space than rlen bytes is needed to
return data, *rbuf can be set to memory allocated with
driver_alloc. This memory will be freed automatically
after call has returned.
The return value is the number of bytes returned in
*rbuf. If ERL_DRV_ERROR_GENERAL is returned
(or in fact, anything <= 0), erlang:port_call/3 will
throw a BAD_ARG.
erl_driver(3), erl_ddll(3), kernel(3), erlang(3)