[erlang-questions] Encode and decode binary data on port driver: undefined symbol ei_decode_version
Brisa Jiménez
brisa.jimenez.f@REDACTED
Thu Nov 22 20:09:18 CET 2012
Hi everyone!
I want to send and receive binary data through Erlang port, and use ei to
encode and decode data, but when I try to test code below the next error
occurs:
Erlang R14B03 (erts-5.8.4) [source] [rq:1] [async-threads:0]
[kernel-poll:false]
Eshell V5.8.4 (abort with ^G)
1> erl_drv:start().
** exception exit: {error,"undefined symbol: ei_decode_version"}
in function erl_drv:start/0
Can anybody give me an example of how do it what I'm want?
I appreciate any advice.
Thanks.
===
-module(erl_drv).
-export([start/0, stop/0, init/1]).
-export([foz/1, baz/1]).
-define(C_LIBRARY, "library").
start() ->
case erl_ddll:load_driver("priv", ?C_LIBRARY) of
ok -> ok;
{error, already_loaded} -> ok;
{error, Reason}-> exit({error, erl_ddll:format_error(Reason)})
end,
spawn(?MODULE, init, [?C_LIBRARY]).
init(?C_LIBRARY) ->
register(erl_drv, self()),
Port = open_port({spawn, ?C_LIBRARY}, [binary]),
loop(Port).
stop() ->
erl_drv ! stop.
foz(Arg)->
call_port({foz, Arg}).
baz(Arg)->
call_port({baz, Arg}).
call_port(Msg) ->
erl_drv ! {call, self(), Msg},
receive
{erl_drv, Res} ->
Res
end.
loop(Port) ->
receive
{call, Caller, {Command, Data}}->
case Command of
foz-> port_control(Port, 3, encode(Data));
baz-> port_control(Port, 4, encode(Data))
end,
receive
{Port, {data, Data}} ->
Caller ! {erl_drv, decode(Data)}
end,
loop(Port);
stop ->
Port ! {self(), close},
receive
{Port, closed} ->
exit(normal)
end;
{'EXIT', Port, Reason} ->
io:format("~p ~n", [Reason]),
exit(port_terminated)
end.
encode(Msg)->
term_to_binary(Msg).
decode(RetVal)->
binary_to_term(RetVal).
===
/* port_driver.c*/
#include <stdio.h>
#include "erl_driver.h"
#include "ei.h"
#include "erl_interface.h"
double foz(double);
double baz(double);
typedef size_t ErlDrvSizeT;
typedef ssize_t ErlDrvSSizeT;
typedef struct {
ErlDrvPort port;
} ptr_port;
static ErlDrvData start(ErlDrvPort port, char *buff)
{
ptr_port* ptr_port1 = (ptr_port*)driver_alloc(sizeof(ptr_port));
set_port_control_flags(port , PORT_CONTROL_FLAG_BINARY);
ptr_port1->port = port;
return (ErlDrvData)ptr_port1;
}
static void stop(ErlDrvData handle)
{
driver_free((char*)handle);
}
static ErlDrvSSizeT control(ErlDrvData handle, unsigned int command,
char *buf, ErlDrvSizeT len,
char **rbuf, ErlDrvSizeT rlen)
{
ptr_port *ptr_port1 = (ptr_port*)handle;
double arg, res;
int version, index = 0;
if (ei_decode_version(buf, &index, &version))
return((ErlDrvSSizeT) ERL_DRV_ERROR_GENERAL);
if (ei_decode_double(buf, &index, &arg))
return((ErlDrvSSizeT) ERL_DRV_ERROR_BADARG);
switch (command) {
case 3:
res = foz(arg);
break;
case 4:
res = baz(arg);
break;
default:
return((ErlDrvSSizeT) ERL_DRV_ERROR_BADARG);
}
index = 0;
if (ei_encode_version(*rbuf, &index)
|| ei_encode_double(*rbuf, &index, res))
return((ErlDrvSSizeT) ERL_DRV_ERROR_ERRNO);
else
return((ErlDrvSSizeT) index);
}
ErlDrvEntry driver_entry = {
NULL, //* F_PTR init, N/A
start, //* L_PTR start, called when port is opened
stop, //* F_PTR stop, called when port is closed
NULL, //* F_PTR output, called when erlang has sent
NULL, //* F_PTR ready_input, called when input descriptor ready
NULL, //* F_PTR ready_output, called when output descriptor ready
"library", //* char *driver_name, the argument to open_port
NULL, //* F_PTR finish, called when unloaded
control, //* F_PTR control, port_command callback
NULL, //* F_PTR timeout, reserved
NULL //* F_PTR outputv, reserved
};
DRIVER_INIT(library) /* must match name in driver_entry */
{
return &driver_entry;
}
===
/*library.c*/
double foz(double x) {
return x/1.0;
}
double baz(double y) {
return y/2.0;
}
===
# Makefile
ERL_ROOT=/usr/local/lib/erlang
all: compile_c compile
compile_c:
@mkdir -p priv
gcc -o priv/library.so -I$(ERL_ROOT)/usr/include/
-I$(ERL_ROOT)/lib/erl_interface-3.7.4/include/ -fpic -shared c_src/*.c
compile:
@mkdir -p ebin
erlc -o ebin/ src/erl_drv.erl
clean:
@rm -rf ebin priv
test:
erl -pa ebin/
.PHONY: c_src
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20121122/7840bf20/attachment.htm>
More information about the erlang-questions
mailing list