[erlang-questions] erlang:port_call and ei library
Brisa Jiménez
brisa.jimenez.f@REDACTED
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:
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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20121126/1f6ed2d9/attachment.htm>
More information about the erlang-questions
mailing list