Thanks David for your fast response.

But I still have problems:

- This is how I defined my native library (dexlib.h)

struct CTypeData 
{
int id;
unsigned long numObjs;
};

class Graph
{
...
bool GetTypeData(int type, CTypeData &tdata);
...
};

- This is my interface file

/* File : dexlib.i */
%module dexlib

%{
#include "dexlib.h"
%}

%include <wchar.i>
%include "cs_struct.i"
cs_struct(CTypeData, TypeData);

%ignore DbGraph::DbGraph (Session *sess);

/* Let's just grab the original header file here */
%include "dexlib.h"

- But Graph is still using the generated CTypeData.cs which handles the native CTypeData (instead of using the struct TData I have written for C#)

  public bool GetTypeData(int type, CTypeData tdata) {
    bool ret = dexlibPINVOKE.Graph_GetTypeData(swigCPtr, type, CTypeData.getCPtr(tdata));
    if (dexlibPINVOKE.SWIGPendingException.Pending) throw dexlibPINVOKE.SWIGPendingException.Retrieve();
    return ret;
  }


In fact, I have the same results whether I add "cs_struct(CTypeData, TypeData)" to my interface file or not. So I guess I'm doing something wrong. Should I add it in a different place into my interface file?

To give you more information, I have added the output I get when executing swig.

Thanks,
Sergio


C:\Users\sgomez\swigwin-2.0.2\Examples\csharp\DEX>..\..\..\swig.exe -v -debug-t
pemap -debug-classes -c++ -csharp dexlib.i
Language subdirectory: csharp
Search paths:
   .\
   .\swig_lib\csharp\
   C:\Users\sgomez\swigwin-2.0.2\Lib\csharp\
   \csharp\
   .\swig_lib\
   C:\Users\sgomez\swigwin-2.0.2\Lib\
   \
Preprocessing...
Starting language-specific parse...
Processing types...
C++ analysis...
Generating wrappers...
Classes
------------
GraphPool
DbGraph
DEX
Graph
RGraph
Session
CTypeData
---[ typemaps ]--------------------------------------------------------------
::: scope 0

Hash(0x570448) {
  'wchar_t' : Hash(0x5ac808) {..........},
  'p.wchar_t' : Hash(0x5acac8) {..........},
  'r.q(const).bool' : Hash(0x5a2318) {.............},
  'long' : Hash(0x5a26d8) {..............},
  'float' : Hash(0x5a28d8) {.............},
  'r.q(const).int' : Hash(0x5a2618) {.............},
  'int' : Hash(0x5a25d8) {..............},
  'r.q(const).unsigned short' : Hash(0x5a2598) {.............},
  'unsigned short' : Hash(0x5a2558) {..............},
  'r.q(const).long' : Hash(0x5a2718) {.............},
  'r.q(const).unsigned int' : Hash(0x5a2698) {.............},
  'unsigned int' : Hash(0x5a2658) {..............},
  'r.q(const).unsigned char' : Hash(0x5a2498) {.............},
  'unsigned char' : Hash(0x5a2458) {.............},
  'signed char' : Hash(0x5a23d8) {.............},
  'r.q(const).signed char' : Hash(0x5a2418) {.............},
  'r.q(const).short' : Hash(0x5a2518) {.............},
  'double' : Hash(0x5a2958) {.............},
  'r.q(const).double' : Hash(0x5a2998) {.............},
  'size_t' : Hash(0x5ab0f8) {..............},
  'r.q(const).size_t' : Hash(0x5ab118) {.............},
  'a(ANY).char' : Hash(0x5a1f48) {................},
  'r.q(const).unsigned long long' : Hash(0x5a2898) {.........},
  'unsigned long long' : Hash(0x5a2858) {.............},
  'r.q(const).long long' : Hash(0x5a2818) {.............},
  'long long' : Hash(0x5a27d8) {.............},
  'r.q(const).float' : Hash(0x5a2918) {.............},
  'p.char' : Hash(0x5a1d88) {..................},
  'r.q(const).unsigned long' : Hash(0x5a2798) {.............},
  'unsigned long' : Hash(0x5a2758) {..............},
  'r.p.char' : Hash(0x5a31a8) {..........},
  'char' : Hash(0x5a2358) {.............},
  'bool' : Hash(0x5a22d8) {.............},
  'p.void' : Hash(0x5aa6d8) {.},
  'void' : Hash(0x5a29d8) {.........},
  'a(ANY).SWIGTYPE' : Hash(0x5a1ff8) {...},
  'a(ANY).a(ANY).SWIGTYPE' : Hash(0x5a2058) {..},
  'p.SWIGTYPE' : Hash(0x5a20b8) {.......................},
  'SWIGTYPE' : Hash(0x5a2178) {.............................},
  'a().SWIGTYPE' : Hash(0x5a33d8) {.................},
  'r.SWIGTYPE' : Hash(0x5a3528) {......................},
  'm(CLASS).SWIGTYPE' : Hash(0x5a35e8) {.....................},
  'r.q(const).p.SWIGTYPE' : Hash(0x5a7a28) {........},
  'r.a(ANY).SWIGTYPE' : Hash(0x5ab3a8) {......................},
  'q(const).p.SWIGTYPE' : Hash(0x5ab718) {......................},
  'r.q(const).enum SWIGTYPE' : Hash(0x5abbf8) {..............},
  'enum SWIGTYPE' : Hash(0x5ac3f8) {....................},
  'short' : Hash(0x5a24d8) {..............},
  'p.q(const).char' : Hash(0x5a1e28) {..},
  'a().char' : Hash(0x5a1f98) {................},
  'r.q(const).char' : Hash(0x5a2398) {.............},
}
-----------------------------------------------------------------------------

On Mar 28, 2011, at 10:59 PM, David Piepgrass wrote:

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)