[Swig-user] return a struct by reference without creating a handler wrapper class

1,366 views
Skip to first unread message

Sergio Gómez Villamor

unread,
Mar 28, 2011, 4:42:48 PM3/28/11
to swig...@lists.sourceforge.net
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) 

David Piepgrass

unread,
Mar 28, 2011, 4:50:26 PM3/28/11
to Sergio Gómez Villamor, swig...@lists.sourceforge.net

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.

cs_struct.i

David Piepgrass

unread,
Mar 28, 2011, 4:59:52 PM3/28/11
to Sergio Gómez Villamor, swig...@lists.sourceforge.net

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

Sergio Gómez Villamor

unread,
Mar 30, 2011, 1:25:55 AM3/30/11
to David Piepgrass, swig...@lists.sourceforge.net
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?


Thanks,
Sergio

David Piepgrass

unread,
Mar 30, 2011, 1:16:41 PM3/30/11
to Sergio Gómez Villamor, swig...@lists.sourceforge.net

Oh, I see the problem. Or at least the main problem. The macro is called %cs_struct, not cs_struct. Add a %.

 

%include "cs_struct.i"

cs_struct(CTypeData, TypeData);

Sergio Gómez Villamor

unread,
Mar 31, 2011, 3:38:00 AM3/31/11
to David Piepgrass, swig...@lists.sourceforge.net
Hi David,

The C# struct I have written is called TypeData (it was an error when I wrote the mail).

Now, my code is in namespaces, as you suggested and I have added an %ignore clause for CTypeData. As well, I have updated cs_struct(X,Y) for %cs_struct(X,Y). But I still have problems and generated code is not as I expected.

This is my interface file at this moment:


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

%{
#include "dexlib.h"
%}

%include <wchar.i>
%include cs_struct.i

%cs_struct(DEXLIB::CTypeData, TypeData);

%nspace DEXLIB::DEX;
%nspace DEXLIB::GraphPool;
%nspace DEXLIB::Session;
%nspace DEXLIB::Graph;
%nspace DEXLIB::DbGraph;
%nspace DEXLIB::RGraph;
%nspace DEXLIB::ObjectType;

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

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


All classes are defined into the DEXLIB namespace.


Although there is an ignore clause for CTypeData, it is still generated as a native handler class and Graph (at C# code) updates an instance of this class

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


Firstly, I do not understand why %ignore DEXLIB::CTypeData is not working (although it works for the other ignore clause I have).

Finally, cs_struct seems is not working (I have also tested using %cs_struct(DEXLIB::CTypeData, DEXLIB.TypeData) or cs_struct(CTypeData, TypeData) and they do not work).

Thanks,
Sergio

David Piepgrass

unread,
Mar 31, 2011, 3:39:02 PM3/31/11
to Sergio Gómez Villamor, swig...@lists.sourceforge.net

Sorry, I don’t know what’s wrong. I suggest that you try something simple such as this:

 

%{

    struct Point2D {

        int X, Y;
    };

%}

%cs_struct(Point2D, System.Drawing.Point)

%inline %{

    void Test1(Point2D p) {}

    void Test2(Point2D& p) {}

%}

 

If Test1 and Test2 are wrapped correctly, look for the differences between this code and your code.

Sergio Gómez Villamor

unread,
Apr 1, 2011, 9:40:37 AM4/1/11
to David Piepgrass, swig...@lists.sourceforge.net
Thanks David,

Starting from this simple example, I could do the same with my structure.

Anyway, I have some questions?

- If I use common data types into the structure (int, long, double...) I have no problems, but if I try to add an string into the struct, then it fails (AccessViolationException). I have tried "std::string" and "wchar_t *" with no success (of course I have added corresponding "std_wstring.i" or "wchar.i" to do that). Is there something I should take into account or cs_struct has not been though to do that?

- cs_struct just works for C#, what about java? I remember you told me you do not know how to do this for Java. Would you tell me if there is someone else who could help me with Java?

Thanks,
Sergio

Sergio Gómez Villamor

unread,
Apr 1, 2011, 10:34:03 AM4/1/11
to Daniel Mostovoy, swig...@lists.sourceforge.net
Mmm... in fact I'm using std::wstring and the typemap for this (std_wstring.i).
Then, do you think it should work? If so, could you provide me a simple example? As before, this way I could check out what I'm doing wrong.

Thanks,
Sergio


On Apr 1, 2011, at 4:10 PM, Daniel Mostovoy wrote:

Sergio... are you using the typemap for std::string? It comes with the swig distro & is called string.i i think... d.
------------------------------------------------------------------------------ Create and publish websites with WebMatrix Use the most popular FREE web apps or write code yourself; WebMatrix provides all the features you need to develop and publish your website. http://p.sf.net/sfu/ms-webmatrix-sf
_______________________________________________ Swig-user mailing list Swig...@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/swig-user


Sergio Gómez Villamor

unread,
Apr 1, 2011, 10:53:48 AM4/1/11
to Daniel Mostovoy, swig...@lists.sourceforge.net
No, I have tested stl strings (or wstrings) and "wchar *" with no problems when they are member variables or arguments of methods into a wrapped class.

My problem is when I want to return an struct without using for that a wapped class. I explained this in detail here:
Thanks to David and using and interface file he provided me (cs_struct) with different typemaps, I could do it for C# (not for Java yet).
But I get in problems when I have a stl string into the structure. Maybe this case cannot be solved?

Thanks,
Sergio

On Apr 1, 2011, at 4:40 PM, Daniel Mostovoy wrote:

Sergio...

You're having trouble wrapping a C++ class with an stl string as a member variable? Is that correct? sorry I've not been following this thread from the beginning...

d.

Sergio Gómez Villamor

unread,
Apr 1, 2011, 11:59:02 AM4/1/11
to Daniel Mostovoy, swig...@lists.sourceforge.net
I want to return a "copy" of the C++ structure as a C#/Java structure instead of getting a C#/Java structure which manages a native instance. This is because I don't want accessing to a native instance  to access a field into the C#/Java structure. 

That is, if a method returns an structure and this structure won't be updated anymore... why it is necessary to going down to the native access each time I want access a field of the structure in the target language?

For example, 
%{
    struct Point2D {
        int X, Y;
    };
%}
%cs_struct(Point2D, System.Drawing.Point)
%inline %{
    void Test1(Point2D p) {}
    void Test2(Point2D& p) {}
%}

this maps a C++ struct with the System.Drawing.Point class defined at C#, so once Test1 or Test2 has been executed, I will access Point instance as a common C# object (a Point2D wrapper handler class is not generated).

The proble is, what happens if I have an stl string or a wchar_t * moreover of "int X,Y" ?


Maybe this could be done easier, what do you mean exactly by "return a copy"? Could you provide an example?


Thanks,
Sergio 


On Apr 1, 2011, at 5:19 PM, Daniel Mostovoy wrote:

Hi Sergio...

i don't have experience wrapping structs - though i'd imagine that they'd behave just like public classes...  i did notice in your sourceforge query that your getter function is getting the object by reference... if you want a copy of the struct in the target language why not return a copy? i believe swig handles such cases well - i do it all the time. Judging by the simplicity of my anwer, i'm guessing I'm not understanding your problem :-)

re wrapping for java as a target language - swig needs to know your target package name for it to work properly. not sure if you know this, i'm just mentioning it because it took me forever to figure this out for myself :-) if you're using anything other than the default package you MUST use the -package option with swig. run swig -help for a complete list of options ... I also find the - outdir super useful to put the resultant .java files right into your package.

good luck!

d.

David Piepgrass

unread,
Apr 1, 2011, 12:23:47 PM4/1/11
to Sergio Gómez Villamor, swig...@lists.sourceforge.net

When using %cs_struct, other typemaps such as std_wstring.i will have no effect. %cs_struct causes the structure to be passed *bitwise*, and the .NET marshaler is in charge of converting your C# structure to a C++ structure or vice versa. Therefore you can’t use std::string or std::wstring in your structure. You might be able to use wchar_t* in C++, and extract the string in C# using one of two methods:

 

1.       Put “public IntPtr strPtr;” in the C# structure and use System.Runtime.InteropServices.Marshal.PtrToStringUni(strPtr); to extract the string

2.       Put “[MarshalAs(UnmanagedType.LPWStr)] public string str;” in the C# structure. I haven’t tried this, but if you’re lucky it’ll make the marshaller extract the string automatically.

 

I don’t know who on this list would be an expert in SWIG for Java and JNI.

Sergio Gómez Villamor

unread,
Apr 1, 2011, 1:19:06 PM4/1/11
to David Piepgrass, swig...@lists.sourceforge.net
Yes that is what I thought. Thanks for the explanation.

I have tested your first suggestion and it worked, but I have a question

I have this in the C# structure

public struct TypeData {
    private int id;
    private IntPtr name;
    public int GetId() { return id; }
    public string GetName() { return System.Runtime.InteropServices.Marshal.PtrToStringUni(name); }
}

and this in the C++ structure

struct TypeData {
int id;
const wchar_t *name;
};

and I guess "IntPtr name" and "wchar_t *name" are two pointers referencing the same memory address. Since this wchar buffer should be released when the C# TypeData structure is released, how could I do that? Should I add a destructor to my C# TypeData and release from ther the "IntPtr name"?

If I solve this, I promise I will stop disturbing you :-)

thanks,
Sergio

David Piepgrass

unread,
Apr 1, 2011, 1:26:20 PM4/1/11
to Sergio Gómez Villamor, swig...@lists.sourceforge.net

If you want to allocate the string on the C++ side and release it on the C# side, given that %cs_struct bypassed SWIG’s normal wrapping, I suppose the best option is BSTRs. On the C++ side you call SysAllocString or SysAllocStringLen to create a BSTR that you put in the structure. Then in C# call Marshal.PtrToStringBSTR to convert the IntPtr (which points to the BSTR) to System.String, and finally release the string with Marshal.FreeBSTR.

Sergio Gómez Villamor

unread,
Apr 1, 2011, 1:39:06 PM4/1/11
to David Piepgrass, swig...@lists.sourceforge.net
OK, I will try this although I don't like it very much because if I have to allocate the string using SysAllocString, that means the allocation of the string will depend on the target language I'm compiling to.

Anyway, I will try this next week (it's my time to leave). 

Thanks very much,
Sergio

David Piepgrass

unread,
Apr 1, 2011, 7:24:36 PM4/1/11
to Sergio Gómez Villamor, swig...@lists.sourceforge.net

Well, you could also allocate the string with malloc() and wrap free() with SWIG:

 

%cs_struct(void*, IntPtr)

void free(void* ptr);

 

From: Sergio Gómez Villamor [mailto:sgo...@ac.upc.edu]
Sent: Friday, April 01, 2011 11:39 AM
To: David Piepgrass
Cc: swig...@lists.sourceforge.net
Subject: Re: [Swig-user] return a struct by reference without creating a handler wrapper class

 

OK, I will try this although I don't like it very much because if I have to allocate the string using SysAllocString, that means the allocation of the string will depend on the target language I'm compiling to.

Sergio Gómez Villamor

unread,
Mar 29, 2011, 5:59:35 AM3/29/11
to David Piepgrass, swig...@lists.sourceforge.net
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:

Sergio Gómez Villamor

unread,
Apr 4, 2011, 2:07:48 AM4/4/11
to Sergio Gómez Villamor, swig...@lists.sourceforge.net
Just ignore this last mail... I sent it some days ago and the list's moderator accepted it now.

Thanks,
Sergio

On Mar 29, 2011, at 11:59 AM, Sergio Gómez Villamor wrote:

> Thanks David for your fast response.
>
> But I still have problems:
>
> - This is how I defined my native library (dexlib.h)

Sergio Gómez Villamor

unread,
Apr 4, 2011, 3:27:35 AM4/4/11
to David Piepgrass, swig...@lists.sourceforge.net
Hi David,


I prefer this approach about wrapping free, but cs_struct(void *, IntPtr) neither cs_struct(void *, System.IntPtr) didn't work. Have you tried them?



On the other side, together with the cs_struct module, you give a cs_class module to be used with a C# class instead of a C# struct. I have been testing it but I think there is an error:
- Using cs_struct, resulting wrapper function is as follows:
[DllImport("dexlib", EntryPoint="CSharp_dex_Graph_TypeData")]
public static extern bool dex_Graph_GetTypeData(HandleRef, jarg1, int jarg2, ref edu.upc.dama.dex.TypeData jarg3);
- But using cs_class, resulting wrapper function is:
[DllImport("dexlib", EntryPoint="CSharp_dex_Graph_TypeData")]
public static extern bool dex_Graph_GetTypeData(HandleRef, jarg1, int jarg2,  edu.upc.dama.dex.TypeData jarg3);

Note the difference is there is no "ref" modifier in the third argument when using cs_class. Is this an error of the cs_class module?


Thanks,
Sergio

David Piepgrass

unread,
Apr 4, 2011, 4:45:03 PM4/4/11
to Sergio Gómez Villamor, swig...@lists.sourceforge.net

In what way doesn’t it work? I haven’t actually tried %cs_struct(void*, IntPtr), but I do use %cs_struct(HWND, IntPtr), %cs_struct(HBITMAP, IntPtr), etc.

 

It is correct that there is no “ref” on TypeData using %cs_class. TypeData is supposed to be a class, so it is already passed by reference. “ref TypeData” would correspond to CTypeData** in C++.

Sergio Gómez Villamor

unread,
Apr 5, 2011, 2:26:56 AM4/5/11
to David Piepgrass, swig...@lists.sourceforge.net
When I add this to my interface file,
void free(void *)
swig generates a SWIGTYPE_p_void.cs, as expected.

But when I add this to my interface file,
%cs_struct(void *, System.IntPtr);
%ignore void *;
void free(void *ptr);
if fails as follows:

C:\Users\sgomez\swigwin-2.0.2\Examples\csharp\DEX>..\..\..\swig.exe -c++ -v -deb
ug-typemap -debug-classes -csharp -namespace edu.upc.dama 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...
dexlib.i(36) : Error: Syntax error in input(1).

Line 36 corresponds to the cs_struct(void *, IntPtr) line. I've been looking for a kind of parse debug option for the swig command line but I haven't found it, so I have no more information about what is going wrong. Of course, "cs_struct.i" has been included (in fact, I have previous use of cs_struct working properly).


Also, I have tested your HWND use case:
%cs_struct(HWND, IntPtr);
HWND GetConsoleHwnd(void);
and it works:
  [DllImport("dexlib", EntryPoint="CSharp_GetConsoleHwnd")]
  public static extern  IntPtr  GetConsoleHwnd();


And If I do something like that:
typedef void * voidPtr;
%cs_struct(voidPtr, IntPtr);
void MyFree(voidPtr ptr)
{
free(ptr);
}
it also works. 

So I asked if you have tested cs_struct with void * before. Anyway, I could manage it using this typedef but maybe you know a clever way to get void * working with cs_struct. 




Regarding to my cs_struct/cs_class problem I solved it.



Thanks a lot once again,
Sergio
Reply all
Reply to author
Forward
0 new messages