I've read the swig basics, and the ruby section, and looked through a
number of the examples, but most of my typemaps seem to have no real
effect, I'm not sure why, and for all my effort I'm not getting
any further.

Basically, our library has opaque contexts, and all function return
values are status codes, function outputs are always through reference
arguments. I don't know how to deal with them. Basically, we have a
fairly classic OO-in-C API like:

	typedef struct _Params* Params;
	typedef struct _Ctx* Ctx;

	int ParamsCreate(int i, Params* p);
	int ParamsGet(Params p, int* i);
	int CtxBegin(Params p, size_t fooSz, const unsigned char* foo, Ctx* c);
	int CtxGet(Ctx c, size_t* fooSz, unsigned char* foo);
	int CtxDo(Ctx c, size_t length, const unsigned char* in, unsigned char* out);
	int CtxEnd(Ctx* c);
	int ParamsDestroy(Params* p);

You create objects, you don't know there internal structure, sometimes
you create another object that refers to the first, and all operations
are functions that take the opaque structs as arguments.

The above is my actual code, if I can swig that, I can swig all our
(real) APIs, which would be great.

Below is my example.i, it compiles and can be loaded, but
just doesn't work like I would expect, comments are inline.

Can anybody help?

Thanks!
Sam

Btw, I'm using swig 1.3.19


%module example
%{
#include "example.h"
%}

// The "SWIG Basics" gives me the idea this might be necessary, though
// its absence hasn't caused me problems:
//   typedef unsigned int size_t;

// From example: pointer/example.i
//
// These may be useful, if I knew what they did!
//
// %include cpointer.i
// %pointer_functions(int, intp);
//
// Also, the %apply directive might help in applying my typmap rules
// to the C headers, without having to copy the header into the .i file
// and modify all the declarations!




%include typemaps.i

// From: example.h

typedef struct _Params* Params;
typedef struct _Ctx* Ctx;


// - creating opaque objects
//
// FIXME: This isn't working, Example::ParamsCreate in ruby still takes two
// arguments!

int ParamsCreate(int i, Params* OUTPUT);



// - output integers works
//
// FIXME: can I turn all non-zero return values into a Ruby exception?

int ParamsGet(Params p, int* OUTPUT);



// - input buffers
//
// FIXME: this isn't working!

// It's a little clunky, but if it worked I'd be willing to do it!
//

// I tried to take a hint from the Basics chapter, and did this:
/*
~/w/tk/samples/sb4r % irb -r example
irb(main):002:0> Example.CtxBegin(nil, 3, "abc", 4)
TypeError: wrong argument type String (expected Data)
        from (irb):2:in `CtxBegin'
        from (irb):2

*/
// I tried the code from the Examples/ruby:
//
%typemap(in) (size_t inSz, const unsigned char *in) {
  $1 = (size_t) RSTRING($input)->len;
  $2 = STR2CSTR($input);
};

// And I tried the code from http://www.swig.org/Doc1.3/Library.html:

// %apply (char *STRING, int LENGTH) { (size_t fooSz, const unsigned char *str) };

// Nothing is working!

int CtxBegin(Params p, size_t fooSz, const unsigned char* foo, Ctx* OUTPUT);



// - output buffers
//
// FIXME: I don't know how to do this. In C, you have to call CtxGet() twice,
// usually, once with foo being null, to get the output size, then you malloc
// the output buffer, then you call again with *fooSz the buffer size, on return
// it will be the (possibly smaller) number of bytes written to foo.

int CtxGet(Ctx c, size_t* fooSz, unsigned char* foo);



// Q5 - mutating buffers
//
// Is this considered bad practice? There are huge efficiency gains to be made
// when you don't force dynamic allocation for your output! It's like a ruby
// "!"-method.

%typemap(in)(size_t sz, const unsigned char* in, unsigned char* out) {
  $1 = (size_t) RSTRING($input)->len;
  $2 = STR2CSTR($input);
  $3 = STR2CSTR($input);
}

int CtxDo(Ctx c, size_t length, const unsigned char* in, unsigned char* out);


// Q6 - destroying opaque objects
//
// FIXME: these are both destructors
int CtxEnd(Ctx* c);

int ParamsDestroy(Params* p);