0

I am new to using SWIG and struggling with making a Python typemap for the following struct:

typedef struct si2drExprT
{
    si2drExprTypeT type;
    union
    {
        si2drInt32T i;
        si2drFloat64T d;
        si2drStringT s;    /* most likely an identifier */
        si2drBooleanT b;
    } u;

    si2drValueTypeT valuetype; /* if the type is a fixed value */

    struct si2drExprT *left; /* the exprs form a classic binary tree rep of an arithmetic expression */
    struct si2drExprT *right;
} si2drExprT;

It is currently being used in one function call:

si2drVoidT    si2drIterNextComplexValue ( si2drValuesIdT iter,
  si2drValueTypeT *type,
  si2drInt32T     *intgr,
  si2drFloat64T   *float64,
  si2drStringT    *string,
  si2drBooleanT   *boolval,
  si2drExprT      **expr,
  si2drErrorT     *err )

I need si2drExprT **expr to be an output not a pointer. I have successfully made several other pointers outputs using %apply int *OUTPUT { si2drErrorT* err }; format.

I have read most of the SWIG documentation on typemaps and Python typemaps. I am pretty confident I understand the concept of how they are written and how they work, but the intricacy of how this struct should be typemapped is stumping me.

I cannot switch to ctypes because eventually I will need to do the same thing for Perl and SWIG seems to be the best option for converting to multiple languages (that I know about). I also have no control over how the C function is defined. My wrapper conversion has to be independent of the C library.

Can someone offer me an example of what to do? I cannot seem to find the level of example I need anywhere.

I would truly appreciate any help provided.

-- EDIT --

My intended use in Python is to look something like this:

(some_int, some_flt, some_str, some_bool, some_expr, error) = si2drIterNextComplexValue(some_iter)

Where the some_expr value is a tuple or dict or something. That may not be possible exactly but I am open to suggestions on how to make it an output in some format that I can then use in Python to extract the defined union values from.

All of the pointer arguments to the C function are intended as outputs where the *type tells the user which pointer value to look at.

timrau
  • 22,578
  • 4
  • 51
  • 64
HGarrett
  • 21
  • 3

1 Answers1

0

With SWIG you can change the interface completely. For example you could create a new class in your .i file which stores the pointer, and return an instance of that class:

// .i file: 

... what you have already to export si2dr* types ...

struct ExprWrapper {
    si2drValueTypeT type;
    si2drInt32T     intgr;
    si2drFloat64T   float64,
    si2drStringT    string;
    si2drBooleanT   boolval;
    si2drExprT      *expr;
    si2drErrorT     err;
};

%inline %{
ExprWrapper si2drIterNextComplexInt(si2drValuesIdT iter) {
    ExprWrapper wrapper;
    si2drIterNextComplexInt(iter, & wrapper.type, ..., & wrapper.expr, & wrapper.err);
    return wrapper;
)
%}

You might have to tell SWIG about who owns the expr field of ExprWrapper (you or Python -- see SWIG docs), but this approach should be rather straightforward.

Oliver
  • 27,510
  • 9
  • 72
  • 103
  • I have resorted to using a previous version of the c library I am converting that doesn't need this structure for now. – HGarrett Aug 27 '14 at 20:44
  • OK, but you should consider trying the above in case it works, it will benefit others – Oliver Aug 28 '14 at 04:26
  • Sure, I must have not posted my entire comment. The second half of it was I am not entirely sure how this helps replace the union? I see how it will help replace the int/float/bool/string part of the method call but not the *expr. – HGarrett Aug 28 '14 at 14:36
  • Can you perhaps extend your answer to show how you would like to use this from python? – Oliver Aug 28 '14 at 15:31
  • I think I added what you asked for, please let me know if that is not sufficient. – HGarrett Aug 28 '14 at 21:16