swiggery

M

Martin DeMello

I have some C code with two exported functions, which I'm trying to wrap
via swig. THe signatures are:

int dawg_init(char *filename, NODE ** dawgp, INDEX * nedgesp);
void processRack(NODE *dawg, char *rack);

where NODE and INDEX are C typedefs for long.

In the C code, I say

NODE *dawg;
INDEX nedges;
char *rack;

dawg_init(dictFileName, &dawg, &nedges);
processRack(dawg, rack);

How do I get swig to have my ruby code look like

dawg = dawg_init(dictFilename)
processRack(dawg, rack)

martin
 
S

Steven Jenkins

Martin said:
I have some C code with two exported functions, which I'm trying to wrap
via swig. THe signatures are:

int dawg_init(char *filename, NODE ** dawgp, INDEX * nedgesp);
void processRack(NODE *dawg, char *rack);

where NODE and INDEX are C typedefs for long.

In the C code, I say

NODE *dawg;
INDEX nedges;
char *rack;

dawg_init(dictFileName, &dawg, &nedges);
processRack(dawg, rack);

How do I get swig to have my ruby code look like

dawg = dawg_init(dictFilename)
processRack(dawg, rack)

I have to head out to run some errands, but here are some quick hints.
First of all, if these two functions are all you're trying to wrap, SWIG
is probably overkill. SWIG is best for large libraries where you're
willing to settle for the un-Rubyness of the wrapped API in return for
having the wrappers automatically generated. For two functions, I'd
probably hand-code the wrappers as described in the Pickaxe--especially
if you want to change the method signatures. Or use Ruby Inline, about
which I know little except that it exists and looks interesting.

The SWIG technique for handling function arguments that are for return
values only is the 'argout' typemap. Here's an example from one of my
SWIG interface files:

-------- snip ---------

/*
* Input typemap for output structs
*/

%typemap(ruby, in, numinputs=0) struct any *OUTPUT {
$1 = ALLOC($*1_type);
}

/*
* Argout typemap for output structs
*/


%typemap(argout, fragment="output_helper") struct any *OUTPUT {
$result = output_helper($result,
SWIG_NewPointerObj($1, $1_descriptor, 1));
}

/*
* Apply above rules to output structs not requiring special handling
*/

%apply(struct any *OUTPUT) {
CAPI_CATC_T *catcP,
CAPI_USERINFO_T *userinfoP,
CAPI_DIAG_SYMBOL_T *symbP,
CAPI_DIAG_T *OUTPUT,
CAPI_FRAME_INFO_T *OUTPUT,
CAPI_FRAME_DEFN_T *fdefnP,
CAPI_FRAME_INFO_T *OUTPUT,
CAPI_FRAME_TYPE_T *ftypeP,
CAPI_ITEMSTATE_E *stateP,
CAPI_ITEM_T *OUTPUT,
CAPI_LINKED_ITEM_T *linkP,
CAPI_LIST_T *OUTPUT,
CAPI_NOTE_T *OUTPUT,
CAPI_PROJECT_T *OUTPUT,
CAPI_QUERY_T *OUTPUT
}

-------- snip ---------

The 'in' typemap generates code to allocate the structure, 'numinputs=0'
tells the wrapper not to expect a corresponding argument in the Ruby
call. The 'argout' typemap wraps the struct (after return from the C
function) in the proper Ruby class and adds it to the array of returned
values. Omitting the int return value from dawg_init will require an
'out' typemap, I think. I've never used those.

The 'in' typemap above is Ruby-specific, because it calls Ruby's wrapper
around malloc(). SWIG doesn't have, or I couldn't find, a
language-independent macro for that. The 'argout' typemap is
language-independent.

But really, I'd just do it by hand. The Ruby C API is pretty sweet.

Back later.

Steve
 
M

Martin DeMello

Steven Jenkins said:
is probably overkill. SWIG is best for large libraries where you're
willing to settle for the un-Rubyness of the wrapped API in return for
having the wrappers automatically generated. For two functions, I'd

Thanks for the reply, Steve, and particularly for that bit - I hadn't
quite caught on to that, and thought it was merely a matter of tweaking the
..i file to get rubyish API out of SWIG. I'll go with handbinding this
time, I think.

martin
 
G

Gennady Bystritsky

SWIG is especially good for a small task as you can get it done in no
time to the extent you would spend tons of time doing manually. If
you care about rubyish API it is also doable, by using SWIG
directives like '%rename' in your interface description file. And the
type mapping is just fabulous.

Gennady.
 
S

Steven Jenkins

Gennady said:
SWIG is especially good for a small task as you can get it done in no
time to the extent you would spend tons of time doing manually. If you
care about rubyish API it is also doable, by using SWIG directives like
'%rename' in your interface description file. And the type mapping is
just fabulous.

SWIG is good for a small task if you know SWIG. I use %rename and
typemaps in my own applications, but I found the learning curve somewhat
steep--not worth climbing, in my experience, for a simple task like
Martin's. If Martin expects to do more work along those lines, the
learning time may be a good investment.

Steve
 
R

raymond medeiros

------=_Part_2537_2755561.1127595158998
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

ARG i'm a ruby pirate into swiggery and eye arrr bee.
 
M

Martin DeMello

Steven Jenkins said:
SWIG is good for a small task if you know SWIG. I use %rename and
typemaps in my own applications, but I found the learning curve somewhat
steep--not worth climbing, in my experience, for a simple task like
Martin's. If Martin expects to do more work along those lines, the
learning time may be a good investment.

Did it by hand in the end - didn't take long at all (though longer than
it should have!). I might go back and try it with SWIG once I'm more
familiar with the hand route, since as you say it will be valuable
knowledge at some point - I think trying to learn both SWIG and C
extensions at the same time was a bit much, though.

martin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,183
Messages
2,570,967
Members
47,517
Latest member
Andres38A1

Latest Threads

Top