[erlang-questions] erlang:port_call and ei library

Brisa Jiménez <>
Mon Nov 26 18:25:00 CET 2012

Hi everyone!

I have doubts about port_call and driver_init structure in a port driver.

This way I open the port:
Port = open_port({spawn, ?C_LIBRARY}, [binary]),

Erlang function:
    call_port({1, Arg}).

C function:
double foz(double x) {
return x/1.0;

I use next BIF to port calls:
erlang:port_call(Port, Command, encode(Data)),
where Command is an integer and Data is a float for example...

And for encode:

This is my driver structure:
ErlDrvEntry driver_entry = {
    NULL, // called at system start up for statically
                // linked drivers, and after loading for
                // dynamically loaded drivers
    stop, // called when port is closed, and when the emulator is halted.
    NULL, //called when we have output from erlang to the port
    NULL, //ready_input - called when we have input from one of the
driver's handles
    NULL, //ready_output - called when output is possible to one of the
driver's handles
    "library", //driver_name - name supplied as command in open_port XXX ?
    NULL, // finish - called before unloading the driver -
                // DYNAMIC DRIVERS ONLY
    NULL, //handle - Reserved -- Used by emulator internally
    NULL, // control - "ioctl" for drivers - invoked by port_control/3
    NULL, //timeout - Handling of timeout in driver
    NULL, //outputv - called when we have output from erlang to the port
    NULL, // ready_async - 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
    call, // call - Works mostly like 'control', a synchronous call into
the driver.
    NULL, // event - Called when an event selected by driver_event() has
.extended_marker = ERL_DRV_EXTENDED_MARKER,
    0, // ERL_DRV_FLAGs
    NULL, // handle2 - Reserved -- Used by emulator internally
    NULL, // process_exit - Called when a process monitor fires
    NULL, // stop_select - Called to close an event object

And my call function:
ErlDrvSSizeT call(ErlDrvData handle, unsigned int command,
char *buf, ErlDrvSizeT len,
char **rbuf, ErlDrvSizeT rlen, unsigned int *flags)
ptr_port *ptr_port1 = (ptr_port*)handle;
    double arg, res;
    int version, index = 0;

    if (ei_decode_version(buf, &index, &version)) return (ErlDrvSSizeT)1;
    if (ei_decode_double(buf, &index, &arg)) return (ErlDrvSSizeT)2;

    switch (command) {
        case 1:
            res = foz(arg);
        case 2:
            res = baz(arg);
            return (ErlDrvSSizeT)3;
    index = 0;
    if (ei_encode_version(*rbuf, &index) ||
    ei_encode_double(*rbuf, &index, res)) return (ErlDrvSSizeT)4;
    return (ErlDrvSSizeT)index;


My erlang version is:
Erlang R14B03 (erts-5.8.4)

My erts version doesn't have ErlDrvSizeT and ErlDrvSSizeT types, so, I
include these types in my port_driver.c file:
typedef size_t ErlDrvSizeT;
typedef ssize_t ErlDrvSSizeT;

When I compile code the next warning is showed:
c_src/port_driver.c:78:5: warning: initialization from incompatible pointer
type [enabled by default]
c_src/port_driver.c:78:5: warning: (near initialization for
‘driver_entry.flush’) [enabled by default]

78 line refers to call in driver_entry structure.

If I ignore the warning happens the next:
1> erl_drv:start().
2> erl_drv:foz(4.0).

=ERROR REPORT==== 26-Nov-2012::11:13:45 ===
Error in process <0.34.0> with exit value:
{badarg,[{erlang,port_call,[erl_port,1,<<33 bytes>>]},{erl_drv,loop,1}]}

I couldn't change the erlang version, and I read that terms send to c call
function are decoded and encoded with ei library.

Does anybody give me an advice?

Thank you very much.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20121126/1f6ed2d9/attachment.html>

More information about the erlang-questions mailing list