Oh, I should add that the usage in your case would be something like this:

 

%include cs_struct.i

cs_struct(CMyStruct, MyStruct)

 

struct CMyStruct {

          int x;

          double y;

          long z;

};

bool getMyData(CMyStruct &cms);

 

You must also define a C# equivalent of the structure called “struct MyStruct”, and compile this definition along with the SWIG-generated files.

 

If you would like to use a C# class instead (“class MyStruct”), use the following macro:

 

////////////////////////////////////////////////////////////////////////////////

// %cs_class(TYPE, CSTYPE)

//

// Maps a C++ struct or class to a C# class that you have written yourself.

// The class should have [StructLayout(LayoutKind.Sequential)] in front of it.

// This macro should be used rather than cs_struct if the structure in question

// is always passed by reference (because it is large). Double pointers and

// references (**, *&) are not supported here, though I think it's possible to

// do so. I suspect that the .NET marshaller copies the class both on input and

// output, so function calls involving it are probably slow.

//

// It seems that if you pass a class to a C++ function as a parameter, any

// changes made by the C++ function will NOT be copied back to C#. So if that's

// what you need, there are two workarounds:

// 1. Pass a C# struct and use %cs_struct instead.

// 2. Change the C++ function to return a pointer to the same parameter that

//    was passed in. Then your C# call will have to look like

//    "a = Klass.Function(a)". Of course, if the function already returns a

//    value then you're in a tough spot. Sorry.

%define %cs_class(TYPE, CSTYPE)

                %ignore TYPE;

                %typemap(ctype)    TYPE*, TYPE&               %{ TYPE* %}

                %typemap(in)       TYPE*, TYPE&               %{ $1 = $input; %}

                %typemap(varin)    TYPE*, TYPE&               %{ $1 = $input; %}

                //%typemap(memberin) TYPE*, TYPE&               %{ $1 = $input; %}

                %typemap(out, null="NULL") TYPE*, TYPE&       %{ $result = $1; %}

                %typemap(imtype, out="IntPtr") TYPE*, TYPE&   %{ CSTYPE %}

                %typemap(cstype)   TYPE*, TYPE&               %{ CSTYPE %}

                %typemap(csin)     TYPE*, TYPE&               %{ $csinput %}

                %typemap(csout, excode=SWIGEXCODE) TYPE*, TYPE& {

                                IntPtr ptr = $imcall;$excode

                                if (ptr == IntPtr.Zero)

                                                return null;

                                CSTYPE ret = (CSTYPE)Marshal.PtrToStructure(ptr, typeof(CSTYPE));

                                return ret;

                }

                %typemap(csvarin, excode=SWIGEXCODE2) TYPE*

                %{

                                set { $imcall;$excode }

                %}

                %typemap(csvarout, excode=SWIGEXCODE2) TYPE*

                %{

                                get {

                                                IntPtr ptr = $imcall;$excode

                                                if (ptr == IntPtr.Zero)

                                                                return null;

                                                CSTYPE ret = (CSTYPE)Marshal.PtrToStructure(ptr, typeof(CSTYPE));

                                                return ret;

                                }

                %}

%enddef

 

 

For my C# wrapper I use the attached macro to do what you want. I do not know how to accomplish the same thing for Java.

 

From: Sergio Gómez Villamor [mailto:sgomez@ac.upc.edu]
Sent: Monday, March 28, 2011 2:43 PM
To: swig-user@lists.sourceforge.net
Subject: [Swig-user] return a struct by reference without creating a handler wrapper class

 

Hi all,

 

I've been testing and evaluating swig to use it in our projects and it looks great. Also, there is a very good documentation and examples, but I cannot find the way to do something I would like.

 

Let's suppose I have this native code:

 

struct CMyStruct {

          int x;

          double y;

          long z;

};

bool getMyData(CMyStruct &cms);

 

Use swig to create a C# or Java wrapper for this code generates a handler class. This handler class stores a native reference to the native object, a set of getters and setters and a "dispose" method to free the native object. This approach is great in most of the cases. 

 

But this way, querying a field to the class into the target language requires a sequence of call methods up to solve the query into the native object. Also, it forces the user of the code into the target language to call the "dispose" method to free the native object.

 

Sometimes, I just want to return a set of data (a structure) which is not necessary to be natively handled (for example, because it won't change anymore). Thus, I would like to define an struct (or a class) into the target language such as this:

 

class MyData {

          private int x;

          private double y;

          private long z;

          public int getX() { return x; }

          // y getter

          // z getter

};

 

map this type to the native type instead of the default wrapper created by swig and getting this methods into the target language:

- C# : bool getMyData(ref MyData md)

- java : bool getMyData(MyData md)

 

This way, the native object is "transformed" into the target object which does not require to access to the native object any more (handling of the native object is not required).

 

I've been reading the documentation and checking out the examples and I guess this can be done with typemaps, but I haven't found how. In case this is already explained into the documentation or even in the examples, please could you tell me where it is exactly? Otherwise, is this possible? And how?

 

Thanks in advance,

 

Sergio Gómez

Project Manager and Senior Software Engineer

Tel. 934054045

 

DAMA-UPC. DATA MANAGEMENT

Universitat Politècnica de Catalunya

Departament d'Arquitectura de Computadors

Edifici C6-S103. Campus Nord.

Jordi Girona 1-3 

08034 Barcelona (Spain)