[erlang-questions] EFFI: The 80% solution to Erlang FFI woes

Joel Reymont <>
Fri Dec 7 14:48:44 CET 2007


I will admit from the start that I'm a staunch hater of the current  
Erlang Foreign Function Interface (FFI, aka linked-in driver  
mechanism). If there's something preventing application of Erlang to a  
wider range of tasks then this must be it!

I'm familiar with the FFI in Haskell, Lisp and OCaml. The current  
linked-in driver mechanism may be no less functional but it beats all  
others in ugliness and complexity... with a VERY LARGE wooden hammer!!!

While the recently mentioned FFI enhancement proposal is being  
considered, I would like to propose EFFI as the 80% solution. I just  
started implementing this API and library for a chapter of my upcoming  
"Hardcore Erlang" book.

Please feel free to ask questions as well as poke holes in the code  
below. The intent is to wrap the POSIX Regex API in /usr/include/ 
regex.h.

Once regex_effi:generate/0 is called you should end up with the files  
cflags.erl, eflags.erl and reg_error.erl with the enumeration handling  
code, as well as regex.erl and regex_driver.c with the rest of the  
wrapper code.

The focus is on using Erlang in a declarative fashion instead of  
typing up lots of XML like EDTK requires.

Without further ado...


-module(regex_effi).

-compile([export_all]).

-include("regex.hrl").

generate() ->
     effi:start(regex),
     effi:struct(regmatch_t, [int64, int64]), % structure with 2 fields
     %% regcomp() flags
     effi:enum(cflags, int,
               [{reg_basic,    8#0000},
                {reg_extended, 8#0001},
                {reg_icase,    8#0002},
                {reg_nosub,    8#0004},
                {reg_newline,  8#0010},
                {reg_nospec,   8#0020},
                {reg_pend,     8#0040},
                {reg_dump,     8#0200}]),
     %% regexec() flags
     effi:enum(eflags, int,
               [{reg_notbol,   8#00001},
                {reg_noteol,   8#00002},
                {reg_startend, 8#00004},
                {reg_trace,    8#00400},   % tracing of execution
                {reg_large,    8#01000},   % force large representation
                {reg_backr,    8#02000}]), % force use of backref code
     %% regerror() flags
     effi:enum(reg_error, int,
               [{reg_enosys,  -1},	% reserved
                {reg_nomatch,  1},
                {reg_badpat,   2},
                {reg_ecollate, 3},
                {reg_ectype,   4},
                {reg_eescape,  5},
                {reg_esubreg,  6},
                {reg_ebrack,   7},
                {reg_eparen,   8},
                {reg_ebrace,   9},
                {reg_badbr,   10},
                {reg_erange,  11},
                {reg_espace,  12},
                {reg_badrpt,  13},
                {reg_empty,   14},
                {reg_assert,  15},
                {reg_invarg,  16},
                {reg_illseq,  17}]),
     effi:function("regcomp", regerror, % regerror is the return type
                   [{"preg", out, regex_t}, % output argument
                    {"pattern", ptr, char}, % ptr = pointer
                    {"cflags", cflags}]),
     effi:function("regexec", regerror,
                   [{"preg", out, regex_t},
                    {"string", ptr, char},
                    {"nmatch", int},
                    {"pmatch", regmatch_t, array}, % array of structs  
must be given
                    {"eflags", eflags}]),
     effi:function("regerror", int,
                   [{"errcode", int},
                    {"preg", ptr, regex_t},
                    {"errbuf", ptr, char},
                    {"errbuf_size", int}]),
     effi:function("regfree", void,
                   [{ptr, regex_t}]),
     effi:generate(regex),
     effi:stop(regex).

--
http://wagerlabs.com








More information about the erlang-questions mailing list