.TH driver_entry 3erl "erts 5.9.1" "Ericsson AB" "C Library Functions" .SH NAME driver_entry \- The driver-entry structure used by erlang drivers. .SH DESCRIPTION .LP As of erts version 5\&.9 (OTP release R15B) the driver interface has been changed with larger types for the callbacks \fBoutput\fR\&, \fBcontrol\fR\& and \fBcall\fR\&\&. See driver \fB version management\fR\& in \fBerl_driver\fR\&\&. .LP .RS -4 .B Note: .RE Old drivers (compiled with an \fIerl_driver\&.h\fR\& from an earlier erts version than 5\&.9) have to be updated and have to use the extended interface (with \fBversion management \fR\&)\&. .LP The \fIdriver_entry\fR\& structure is a C struct that all erlang drivers define\&. It contains entry points for the erlang driver that are called by the erlang emulator when erlang code accesses the driver\&. .LP The \fBerl_driver\fR\& driver API functions need a port handle that identifies the driver instance (and the port in the emulator)\&. This is only passed to the \fIstart\fR\& function, but not to the other functions\&. The \fIstart\fR\& function returns a driver-defined handle that is passed to the other functions\&. A common practice is to have the \fIstart\fR\& function allocate some application-defined structure and stash the \fIport\fR\& handle in it, to use it later with the driver API functions\&. .LP 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 necessary, since the emulator must be responsive\&. .LP The driver structure contains the name of the driver and some 15 function pointers\&. These pointers are called at different times by the emulator\&. .LP The only exported function from the driver is \fIdriver_init\fR\&\&. This function returns the \fIdriver_entry\fR\& structure that points to the other functions in the driver\&. The \fIdriver_init\fR\& function is declared with a macro \fIDRIVER_INIT(drivername)\fR\&\&. (This is because different OS\&'s have different names for it\&.) .LP When writing a driver in C++, the driver entry should be of \fI"C"\fR\& linkage\&. One way to do this is to put this line somewhere before the driver entry: \fIextern "C" DRIVER_INIT(drivername);\fR\&\&. .LP When the driver has passed the \fIdriver_entry\fR\& over to the emulator, the driver is \fInot\fR\& allowed to modify the \fIdriver_entry\fR\&\&. .LP .RS -4 .B Note: .RE Do \fInot\fR\& declare the \fIdriver_entry\fR\& \fIconst\fR\&\&. This since the emulator needs to modify the \fIhandle\fR\&, and the \fIhandle2\fR\& fields\&. A statically allocated, and \fIconst\fR\& declared \fIdriver_entry\fR\& may be located in read only memory which will cause the emulator to crash\&. .SH "DATA TYPES" .RS 2 .TP 2 .B \fBErlDrvEntry\fR\& : .LP .nf typedef struct erl_drv_entry { int (*init)(void); /* called at system start up for statically linked drivers, and after loading for dynamically loaded drivers */ #ifndef ERL_SYS_DRV ErlDrvData (*start)(ErlDrvPort port, char *command); /* called when open_port/2 is invoked. return value -1 means failure. */ #else ErlDrvData (*start)(ErlDrvPort port, char *command, SysDriverOpts* opts); /* special options, only for system driver */ #endif void (*stop)(ErlDrvData drv_data); /* called when port is closed, and when the emulator is halted. */ void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); /* called when we have output from erlang to the port */ void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event); /* called when we have input from one of the driver's handles */ void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event); /* called when output is possible to one of the driver's handles */ char *driver_name; /* name supplied as command in open_port XXX ? */ void (*finish)(void); /* called before unloading the driver - DYNAMIC DRIVERS ONLY */ void *handle; /* Reserved -- Used by emulator internally */ ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); /* "ioctl" for drivers - invoked by port_control/3 */ void (*timeout)(ErlDrvData drv_data); /* Handling of timeout in driver */ void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev); /* called when we have output from erlang to the port */ void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData thread_data); void (*flush)(ErlDrvData drv_data); /* called when the port is about to be closed, and there is data in the driver queue that needs to be flushed before 'stop' can be called */ ErlDrvSSizeT (*call)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, unsigned int *flags); /* Works mostly like 'control', a synchronous call into the driver. */ void (*event)(ErlDrvData drv_data, ErlDrvEvent event, ErlDrvEventData event_data); /* Called when an event selected by driver_event() has occurred */ int extended_marker; /* ERL_DRV_EXTENDED_MARKER */ int major_version; /* ERL_DRV_EXTENDED_MAJOR_VERSION */ int minor_version; /* ERL_DRV_EXTENDED_MINOR_VERSION */ int driver_flags; /* ERL_DRV_FLAGs */ void *handle2; /* Reserved -- Used by emulator internally */ void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor); /* Called when a process monitor fires */ void (*stop_select)(ErlDrvEvent event, void* reserved); /* Called to close an event object */ } ErlDrvEntry; .fi .RS 2 .LP .RE .RS 2 .TP 2 .B int (*init)(void): This is called directly after the driver has been loaded by \fIerl_ddll:load_driver/2\fR\&\&. (Actually when the driver is added to the driver list\&.) The driver should return 0, or if the driver can\&'t initialize, -1\&. .TP 2 .B ErlDrvData (*start)(ErlDrvPort port, char* command): This is called when the driver is instantiated, when \fIopen_port/2\fR\& 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: .RS 2 .LP ERL_DRV_ERROR_GENERAL - general error, no error code .RE .RS 2 .LP ERL_DRV_ERROR_ERRNO - error with error code in erl_errno .RE .RS 2 .LP ERL_DRV_ERROR_BADARG - error, badarg .RE .RS 2 .LP If an error code is returned, the port isn\&'t started\&. .RE .TP 2 .B void (*stop)(ErlDrvData drv_data): This is called when the port is closed, with \fIport_close/1\fR\& or \fIPort ! {self(), close}\fR\&\&. Note that terminating the port owner process also closes the port\&. If \fIdrv_data\fR\& is a pointer to memory allocated in \fIstart\fR\&, then \fIstop\fR\& is the place to deallocate that memory\&. .TP 2 .B void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len): This is called when an erlang process has sent data to the port\&. The data is pointed to by \fIbuf\fR\&, and is \fIlen\fR\& bytes\&. Data is sent to the port with \fIPort ! {self(), {command, Data}}\fR\&, or with \fIport_command/2\fR\&\&. Depending on how the port was opened, it should be either a list of integers 0\&.\&.\&.255 or a binary\&. See \fIopen_port/3\fR\& and \fIport_command/2\fR\&\&. .TP 2 .B void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event): .TP 2 .B void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event): This is called when a driver event (given in the \fIevent\fR\& parameter) is signaled\&. This is used to help asynchronous drivers "wake up" when something happens\&. .RS 2 .LP On unix the \fIevent\fR\& is a pipe or socket handle (or something that the \fIselect\fR\& system call understands)\&. .RE .RS 2 .LP On Windows the \fIevent\fR\& is an Event or Semaphore (or something that the \fIWaitForMultipleObjects\fR\& API function understands)\&. (Some trickery in the emulator allows more than the built-in limit of 64 \fIEvents\fR\& to be used\&.) .RE .RS 2 .LP 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 \fISetEvent\fR\& on Windows), this will make the emulator call \fIready_input\fR\& or \fIready_output\fR\&\&. .RE .RS 2 .LP Spurious events may happen\&. That is, calls to \fIready_input\fR\& or \fIready_output\fR\& even though no real events are signaled\&. In reality it should be rare (and OS dependant), but a robust driver must nevertheless be able to handle such cases\&. .RE .TP 2 .B char *driver_name: This is the name of the driver, it must correspond to the atom used in \fIopen_port\fR\&, and the name of the driver library file (without the extension)\&. .TP 2 .B void (*finish)(void): This function is called by the \fIerl_ddll\fR\& driver when the driver is unloaded\&. (It is only called in dynamic drivers\&.) .RS 2 .LP The driver is only unloaded as a result of calling \fIunload_driver/1\fR\&, or when the emulator halts\&. .RE .TP 2 .B void *handle: This field is reserved for the emulator\&'s internal use\&. The emulator will modify this field; therefore, it is important that the \fIdriver_entry\fR\& isn\&'t declared \fIconst\fR\&\&. .TP 2 .B ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen): This is a special routine invoked with the erlang function \fIport_control/3\fR\&\&. It works a little like an "ioctl" for erlang drivers\&. The data given to \fIport_control/3\fR\& arrives in \fIbuf\fR\& and \fIlen\fR\&\&. The driver may send data back, using \fI*rbuf\fR\& and \fIrlen\fR\&\&. .RS 2 .LP 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\&. .RE .RS 2 .LP If the driver wants to return data, it should return it in \fIrbuf\fR\&\&. When \fIcontrol\fR\& is called, \fI*rbuf\fR\& points to a default buffer of \fIrlen\fR\& bytes, which can be used to return data\&. Data is returned different depending on the port control flags (those that are set with \fBset_port_control_flags\fR\&)\&. .RE .RS 2 .LP If the flag is set to \fIPORT_CONTROL_FLAG_BINARY\fR\&, a binary will be returned\&. Small binaries can be returned by writing the raw data into the default buffer\&. A binary can also be returned by setting \fI*rbuf\fR\& to point to a binary allocated with \fBdriver_alloc_binary\fR\&\&. This binary will be freed automatically after \fIcontrol\fR\& has returned\&. The driver can retain the binary for \fIread only\fR\& access with \fBdriver_binary_inc_refc\fR\& to be freed later with \fBdriver_free_binary\fR\&\&. It is never allowed to alter the binary after \fIcontrol\fR\& has returned\&. If \fI*rbuf\fR\& is set to NULL, an empty list will be returned\&. .RE .RS 2 .LP If the flag is set to \fI0\fR\&, data is returned as a list of integers\&. Either use the default buffer or set \fI*rbuf\fR\& to point to a larger buffer allocated with \fBdriver_alloc\fR\&\&. The buffer will be freed automatically after \fIcontrol\fR\& has returned\&. .RE .RS 2 .LP Using binaries is faster if more than a few bytes are returned\&. .RE .RS 2 .LP The return value is the number of bytes returned in \fI*rbuf\fR\&\&. .RE .TP 2 .B void (*timeout)(ErlDrvData drv_data): This function is called any time after the driver\&'s timer reaches 0\&. The timer is activated with \fIdriver_set_timer\fR\&\&. 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\&. .TP 2 .B void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev): This function is called whenever the port is written to\&. If it is \fINULL\fR\&, the \fIoutput\fR\& function is called instead\&. This function is faster than \fIoutput\fR\&, because it takes an \fIErlIOVec\fR\& directly, which requires no copying of the data\&. The port should be in binary mode, see \fIopen_port/2\fR\&\&. .RS 2 .LP The \fIErlIOVec\fR\& contains both a \fISysIOVec\fR\&, suitable for \fIwritev\fR\&, and one or more binaries\&. If these binaries should be retained, when the driver returns from \fIoutputv\fR\&, they can be queued (using \fBdriver_enq_bin\fR\& for instance), or if they are kept in a static or global variable, the reference counter can be incremented\&. .RE .TP 2 .B 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 \fBdriver_async\fR\&\&. 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)\&. .TP 2 .B ErlDrvSSizeT (*call)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, unsigned int *flags): This function is called from \fIerlang:port_call/3\fR\&\&. It works a lot like the \fIcontrol\fR\& call-back, but uses the external term format for input and output\&. .RS 2 .LP \fIcommand\fR\& is an integer, obtained from the call from erlang (the second argument to \fIerlang:port_call/3\fR\&)\&. .RE .RS 2 .LP \fIbuf\fR\& and \fIlen\fR\& provide the arguments to the call (the third argument to \fIerlang:port_call/3\fR\&)\&. They can be decoded using \fIei\fR\& functions\&. .RE .RS 2 .LP \fIrbuf\fR\& points to a return buffer, \fIrlen\fR\& 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 \fIerlang:port_call/3\fR\& to the caller\&. If more space than \fIrlen\fR\& bytes is needed to return data, \fI*rbuf\fR\& can be set to memory allocated with \fIdriver_alloc\fR\&\&. This memory will be freed automatically after \fIcall\fR\& has returned\&. .RE .RS 2 .LP The return value is the number of bytes returned in \fI*rbuf\fR\&\&. If \fIERL_DRV_ERROR_GENERAL\fR\& is returned (or in fact, anything < 0), \fIerlang:port_call/3\fR\& will throw a \fIBAD_ARG\fR\&\&. .RE .TP 2 .B void (*event)(ErlDrvData drv_data, ErlDrvEvent event, ErlDrvEventData event_data): Intentionally left undocumented\&. .TP 2 .B int extended_marker: This field should either be equal to \fIERL_DRV_EXTENDED_MARKER\fR\& or \fI0\fR\&\&. An old driver (not aware of the extended driver interface) should set this field to \fI0\fR\&\&. If this field is equal to \fI0\fR\&, all the fields following this field also \fIhave\fR\& to be \fI0\fR\&, or \fINULL\fR\& in case it is a pointer field\&. .TP 2 .B int major_version: This field should equal \fIERL_DRV_EXTENDED_MAJOR_VERSION\fR\& if the \fIextended_marker\fR\& field equals \fIERL_DRV_EXTENDED_MARKER\fR\&\&. .TP 2 .B int minor_version: This field should equal \fIERL_DRV_EXTENDED_MINOR_VERSION\fR\& if the \fIextended_marker\fR\& field equals \fIERL_DRV_EXTENDED_MARKER\fR\&\&. .TP 2 .B int driver_flags: This field is used to pass driver capability information to the runtime system\&. If the \fIextended_marker\fR\& field equals \fIERL_DRV_EXTENDED_MARKER\fR\&, it should contain \fI0\fR\& or driver flags (\fIERL_DRV_FLAG_*\fR\&) ored bitwise\&. Currently the following driver flags exist: .RS 2 .TP 2 .B \fIERL_DRV_FLAG_USE_PORT_LOCKING\fR\&: The runtime system will use port level locking on all ports executing this driver instead of driver level locking when the driver is run in a runtime system with SMP support\&. For more information see the \fBerl_driver\fR\& documentation\&. .TP 2 .B \fIERL_DRV_FLAG_SOFT_BUSY\fR\&: Marks that driver instances can handle being called in the \fBoutput\fR\& and/or \fBoutputv\fR\& callbacks even though a driver instance has marked itself as busy (see \fBset_busy_port()\fR\&)\&. Since erts version 5\&.7\&.4 this flag is required for drivers used by the Erlang distribution (the behaviour has always been required by drivers used by the distribution)\&. .RE .TP 2 .B void *handle2: This field is reserved for the emulator\&'s internal use\&. The emulator will modify this field; therefore, it is important that the \fIdriver_entry\fR\& isn\&'t declared \fIconst\fR\&\&. .TP 2 .B void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor): This callback is called when a monitored process exits\&. The \fIdrv_data\fR\& is the data associated with the port for which the process is monitored (using \fBdriver_monitor_process\fR\&) and the \fImonitor\fR\& corresponds to the \fIErlDrvMonitor\fR\& structure filled in when creating the monitor\&. The driver interface function \fBdriver_get_monitored_process\fR\& can be used to retrieve the process id of the exiting process as an \fIErlDrvTermData\fR\&\&. .TP 2 .B void (*stop_select)(ErlDrvEvent event, void* reserved): This function is called on behalf of \fBdriver_select\fR\& when it is safe to close an event object\&. .RS 2 .LP A typical implementation on Unix is to do \fIclose((int)event)\fR\&\&. .RE .RS 2 .LP Argument \fIreserved\fR\& is intended for future use and should be ignored\&. .RE .RS 2 .LP In contrast to most of the other call-back functions, \fIstop_select\fR\& is called independent of any port\&. No \fIErlDrvData\fR\& argument is passed to the function\&. No driver lock or port lock is guaranteed to be held\&. The port that called \fIdriver_select\fR\& might even be closed at the time \fIstop_select\fR\& is called\&. But it could also be the case that \fIstop_select\fR\& is called directly by \fIdriver_select\fR\&\&. .RE .RS 2 .LP It is not allowed to call any functions in the \fBdriver API\fR\& from \fIstop_select\fR\&\&. This strict limitation is due to the volatile context that \fIstop_select\fR\& may be called\&. .RE .RE .RE .SH "SEE ALSO" .LP \fBerl_driver(3erl)\fR\&, \fBerl_ddll(3erl)\fR\&, \fBerlang(3erl)\fR\&, kernel(3erl)