Swiggery

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

Martin DeMello wrote:

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

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

···

Steven Jenkins <steven.jenkins@ieee.org> wrote:

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

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.

···

On Sep 24, 2005, at 12:46, Martin DeMello wrote:

Steven Jenkins <steven.jenkins@ieee.org> wrote:

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

Gennady Bystritsky wrote:

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

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

···

On 9/24/05, Steven Jenkins <steven.jenkins@ieee.org> wrote:

Gennady Bystritsky wrote:
> 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

--
2.times { p true }

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

···

Steven Jenkins <steven.jenkins@ieee.org> wrote:

Gennady Bystritsky wrote:
> 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.