15

I am trying to use SWIG to wrap (in C#) some c++ code that contains a template class that itself wraps a std::vector<T>. I have seen various references on the internet on how to declare the templates for the vector types, but can't get this to work with the extra layer of abstraction. This is what I am doing in the interface.i file for example:

// interface.i file    
%module myNamespaceWrapper
%{
#include "myVector.h"  
%}  

%include "myVector.h"
%include "std_string.i"
%include "std_vector.i"

namespace std {
%template(vector_MyType) vector<MyType*>;
%template(vector_Int) vector<int>;
}

namespace myNamespace {
%template(myVectorMyType) myVector<MyType*>;
%template(myVectorInt) myVector<int>;
}

While this seems to create the corresponding C# types correctly by themselves, the std::vector templates that I have tried to define are not applied to other classes which use them internally, included by way of header files. To show you what I mean, there's a c++ class like:

// myVector.h
namespace myNamespace 
{    
    template<class T> 
    class myVector
    {

    private :
        std::vector<T> vect;

    public : 
        myVector(){}
        virtual ~myVector(){}

        virtual const std::vector<T> & getVect()
        {
            return vect;
        }

        virtual T& front()
        {
            return vect.front();
        }
    }
}

Even though I get a vector_MyType class created by SWIG, when it wraps my template class it is not using it and instead giving lots of examples like this:

public class myVectorMyType : global::System.IDisposable {

    public virtual SWIGTYPE_p_p_myNamespace__MyType front() {
        SWIGTYPE_p_p_myNamespace__MyType ret = new SWIGTYPE_p_p_myNamespace__MyType(myNamespaceWrapperPINVOKE.myVectorMyType_front__SWIG_0(swigCPtr), false);
        return ret;
    }

    public virtual SWIGTYPE_p_myNamespace__std__vectorT_myNamespace__MyType_p_t getVect() {
        SWIGTYPE_p_myNamespace__std__vectorT_myNamespace__MyType_p_t ret = new SWIGTYPE_p_myNamespace__std__vectorT_myNamespace__MyType_p_t(myNamespaceWrapperPINVOKE.myVectorMyType_getVect(swigCPtr), false);
        return ret;
    }
}

Please can someone advise what I am missing for SWIG to generate the wrapper using MyType and vector_MyType instead of SWIGTYPE_p_myNamespace__std__vectorT_myNamespace__MyType_p_t and SWIGTYPE_p_p_myNamespace__MyType ?

Is this anything to do with the template getVect() function returning T&, i.e. would I need to do anything differently for the %template(myVectorInt) myVector<int>; case, where int is not a pointer?

SWilliams
  • 691
  • 7
  • 28
  • 2
    Which version of SWIG are you using? I tried your example with 2.0.11 and 3.0.5 and the C# sources where generated correctly, ie: `public virtual vector_MyType getVect() { vector_MyType ret = new vector_MyType(myNamespaceWrapperPINVOKE.myVectorMyType_getVect(swigCPtr), false); return ret; }` – Giorgos Dimtsas Apr 20 '15 at 08:08
  • Thanks for trying this out! I am also using 3.0.5. Since you got it working, I was able to find the problem with my code. It was not exactly as I put in the question, actually I had an extra `using namespace std;` in the `namespace myNamespace {}` section which was causing the problem. Removing this, it works as expected. – SWilliams Apr 20 '15 at 08:37
  • Care to fix the example in the question and write this up as an answer? – Flexo May 23 '15 at 13:56
  • Have you considered C++/CLI instead of SWIG for native integration with C# code? – Aleksey F. Jun 12 '15 at 11:38
  • I did consider this but in my case the C++ is subject to change. Changing the interface file and re-running SWIG seemed to be easier than changing C++/CLI code so I've gone with that. – SWilliams Jun 12 '15 at 16:03

2 Answers2

0

I would recommend avoiding the issue and just create wrappers for each instantiation you need:

class wrap_int : public temp <int>
{
};
Glenn Teitelbaum
  • 10,108
  • 3
  • 36
  • 80
0

In the end I realised my mistake and SWIG generated the classes as expected.

// interface.i file    
%module myNamespaceWrapper
%{
#include "myVector.h"  
%}  

%include "myVector.h"
%include "std_string.i"
%include "std_vector.i"

namespace std {
%template(vector_MyType) vector<MyType*>;
%template(vector_Int) vector<int>;
}

namespace myNamespace {
// using namespace std; // don't include this!
%template(myVectorMyType) myVector<MyType*>;
%template(myVectorInt) myVector<int>;
}

This produced classes like:

public class myVectorMyType : global::System.IDisposable {
  private global::System.Runtime.InteropServices.HandleRef swigCPtr;
  protected bool swigCMemOwn;

  ...

  public virtual vector_MyType getVect() {
    vector_MyType ret = new vector_MyType(myNamespaceWrapperPINVOKE.myVectorMyType_getVect(swigCPtr), false);
    return ret;
  }
}

where the underlying vector_MyType is as per the std_vector.i template:

public class vector_MyType: global::System.IDisposable, global::System.Collections.IEnumerable
    , global::System.Collections.Generic.IList<MyType>
 {...}
SWilliams
  • 691
  • 7
  • 28