[erlang-questions] erlang:port_call and ei library

Steve Vinoski vinoski@REDACTED
Mon Nov 26 19:02:34 CET 2012


For pre-R15 versions of Erlang you should typedef both the ErlDrvSizeT and
ErlDrvSSizeT types to int, rather than the size_t and ssize_t typedefs you
currently have.

Another problem with your code is that the return value of the control
function should be the size of the binary you're returning. If you want
port_call to throw a badarg, just return a value less than 0. For success
your final return value should be index+1, which is the length of the
encoded binary, not index.

--steve



On Mon, Nov 26, 2012 at 12:25 PM, Brisa Jiménez
<brisa.jimenez.f@REDACTED>wrote:

> 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:
> foz(Arg)->
>     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:
> encode(Msg)->
>     term_to_binary(Msg).
>
> 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
>     start,
>     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
> occurred
> .extended_marker = ERL_DRV_EXTENDED_MARKER,
>  .major_version = ERL_DRV_EXTENDED_MAJOR_VERSION,
> .minor_version = ERL_DRV_EXTENDED_MINOR_VERSION,
>     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);
>             break;
>         case 2:
>             res = baz(arg);
>             break;
>         default:
>             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().
> <0.34.0>
> 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.
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20121126/3054fc1b/attachment.htm>


More information about the erlang-questions mailing list