logo       

Re: function pointers in structures and Java: msg#00164

programming.swig

Subject: Re: function pointers in structures and Java

Brian Hawley wrote:


So far, I've been very impressed with SWIG.

We have a large collection of libraries, implemented in C.

To provide for some runtime overloading, and to make the code a bit more "object" like, we do the following:


TYPEDEF(struct _Object, Object)
struct _Object
{
void *privateData;
void *typePrivateData;

PROTOTYPE(Boolean, (*getString), (Object *object, char *name, char **
value_p));
PROTOTYPE(Boolean, (*getInt32), (Object *object, char *name, unsigned lo
ng *value_p));
PROTOTYPE(Boolean, (*getBoolean), (Object *object, char *name, Boolean
*value_p));
PROTOTYPE(Boolean, (*setString), (Object *object, char *name, char *v
alue));
PROTOTYPE(Boolean, (*setInt32), (Object *object, char *name, unsigned lo
ng value));
PROTOTYPE(Boolean, (*setBoolean), (Object *object, char *name, Boolean
value));
PROTOTYPE(Boolean, (*serialize), (Object *object, char **buffer_p, si
ze_t *bufferSize_p));
PROTOTYPE(Boolean, (*getName), (Object *object, char **buffer_p));
};


PROTOTYPE(Object *, new__Object, (char *objectName, char *template));
PROTOTYPE(Boolean, delete__Object, (Object *object));

The PROTOTYPE and TYPEDEF macros help deal with issues where typedef isn't available on a platform's C compiler, or it isn't ANSI-C.

Now, when new__Object is called, it allocates the private data structures, and sets up the function pointers in the structure appropriately.

We are running SWIG with the -no_default option, so it doesn't collide with the new__ and delete__ functions we have.

We would like to be able to use libraries like this from Java applications.

SWIG does just fine, and code like this works fine:

public class Main {
public static void main(String argv[]) {
_Object op;
Object o;
long value;
System.loadLibrary("base");
System.loadLibrary("object");
// TT t1 = new TT();
_TT tt = new _TT();

op = Object.new__Object("abc", "msg.xml");

However, there doesn't seem to be a way to use op, or even Object to access the member functions.

I'm open to suggestions on how this could be accomplished. Ultimately, I'd like to be able to do something like: op.getString(...), but even Object.getString(op,...) would
be fine.

One thought I had was to define actual C functions: Object__getString outside of the struct, and have that Object__getString routine in turn, reference the op argument, and make the actual call....

Like pointers, SWIG can't infer how you want to use these function
pointers. This OO design pattern in C is common enough so maybe something
automated can be done in the future, but for now you have to take a
manual approach to wrapping this. The best solution would be to write a
C++ class to wrap the C struct, then get SWIG to wrap the C++ class.
There are many other ways which involve tricks and hacks and use of typemaps
and SWIG features to bend it into something like a normal Java interface.
Also consider using %extend, but that would be very similar to
writing a C++ class, except you don't need a C++ compiler. I got this
hack together, which might give you some ideas:



%inline %{
typedef int Boolean;
typedef struct _Object Object;
%}

%{
Boolean foo(Object *object, char *name) {
...
return 1;
}

// The real struct
struct _Object
{
Boolean (*foo) (Object *object, char *name);
};
%}

%nodefault;
// typemap so that this parameter doesn't get wrapped for use from Java
%typemap(in, numinputs=0) Object *object %{
$1 = *(struct _Object **)&jarg1; // serious hack!
%}

// What SWIG sees
struct _Object
{
Boolean foo (Object *object, char *name);
};

%inline %{
Object * new__Object(char *objectName, char *template) {
Object *obj = malloc(sizeof(struct _Object));
obj->privateData = obj;
obj->foo = foo;
return obj;
}
%}


Then you can use it from Java like....

_Object obj = example.new__Object("", "");
int ret = obj.foo("hi");

where example is the name of the SWIG module. You should be able to use %extend so that you can use a Java constructor instead of new__Object.

> I am also concerned about the pointer values. For example:
>
> Object.getString takes the Object *, a char *, and a char **. it
> allocates space and returns it in the third argument. the caller is
> responsible for deleting it using another function we have called
> lfree(). The same with getInt32 which passes a pointer to an
> int...although in this case, there is no memory allocated by the
> function...it's just filled in. Are these types of things going to work?
>
You could use %exception to turn the Boolean return into an exception. You really want the get functions to return the value it is getting (a JavaBean getter) and throw an exception if the Boolean return indicates failure. You'll also need to employ lots of typemaps for handling char* and unsigned long* as output parameters if you want to make a decent Java interface. You can do all this with typemaps, but is involved and if you can just write a decent OO C++ interface to your C code, which mirrors the intended Java interface and wrap that.


William




_______________________________________________
Swig maillist - Swig@xxxxxxxxxxxxxxx
http://mailman.cs.uchicago.edu/mailman/listinfo/swig



<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | FAQ | advertise