Erlang includes ei library for handling Erlang binary term format. This entry introduces how to use this library.
1. Pass the one string to C driver from Erlang.
It's pretty simple case, and pass one string argument to C driver from Erlang. It should be passed port_control/3 or erlang:port_control/3 after all arguments should be encoded as binary. The "index" variable are used for pointing position in the buffer.
% echo.erl
-define(DRV_ECHO, 1).
echo(Str) ->
control(?DRV_ECHO, Str).
control(Cmd, Data) ->
[{port, Port}| _] = ets:lookup(echo_table, port),
Bin = term_to_binary(Data),
Res = port_control(Port, Cmd, Bin),
binary_to_term(Res).
% echo_drv.c
#define DRV_ECHO 1
static int control(ErlDrvData drv_data, unsigned int command, char *buf,
int len, char **buf, int rlen) {
int index, type, size, arity ,ver;
char *arg1;
switch(command) {
case DRV_ECHO:
ei_decode_version(buf, &index, &ver);
ei_get_type(buf, &index, &type, &size);
arg1 = new char[size + 1];
}
}
Type of Erlang termIt can obtain type of Erlang term with result of ei_get_type function. All value of types are defined in ei.h.
#define ERL_SMALL_INTEGER_EXT 'a'
#define ERL_INTEGER_EXT 'b'
#define ERL_FLOAT_EXT 'c'
#define ERL_ATOM_EXT 'd'
#define ERL_REFERENCE_EXT 'e'
#define ERL_NEW_REFERENCE_EXT 'r'
#define ERL_PORT_EXT 'f'
#define ERL_PID_EXT 'g'
#define ERL_SMALL_TUPLE_EXT 'h'
#define ERL_LARGE_TUPLE_EXT 'i'
#define ERL_NIL_EXT 'j'
#define ERL_STRING_EXT 'k'
#define ERL_LIST_EXT 'l'
#define ERL_BINARY_EXT 'm'
#define ERL_SMALL_BIG_EXT 'n'
#define ERL_LARGE_BIG_EXT 'o'
#define ERL_NEW_FUN_EXT 'p'
#define ERL_FUN_EXT 'u'
#define ERL_NEW_CACHE 'N'
#define ERL_CACHED_ATOM 'C'
2. Pass the ListIt should call ei_decode_list_header function when parse the list term. It must be called when parse the list term.
% echo_list.erl
-define(DRV_ECHO_LIST, 1).
echo(List) when is_list(List) ->
control(?DRV_ECHO_LIST, List).
control(Cmd, Data) ->
[{port, Port}| _] = ets:lookup(echo_list_table, port),
Bin = term_to_binary(Data),
Res = port_control(Port, Cmd, Str),
binary_to_term(Res).
% echo_drv.c
#define DRV_ECHO 1
static int control(ErlDrvData drv_data, unsigned int command, char *buf,
int len, char **buf, int rlen) {
int index, type, size, arity ,ver;
char *arg1;
switch(command) {
case DRV_ECHO_LIST:
ei_decode_version(buf, &index, &ver);
ei_get_type(buf, &index, &type, &size);
if(type == ERL_LIST_EXT) {
ei_decode_list_header(buf, &index, &arity);
printf("number of elements: %d\n", arity);
ei_get_type(buf, &index, &type, &size);
swithc(type) {
case ERL_SMALL_INTEGER_EXT:
case ERL_INTEGER_EXT:
break;
case ERL_STRING_EXT:
break;
}
}
}
}