Ok, the title is a bit long, but I couldn't figure out a shorter one :) So let me explain.
I have a C++ codebase where we have some container classes. Those classes have access methods returning items by reference or const reference. Then in another part of the codebase, I have containers of heap allocated object
's, which are using the director feature.
And I can't figure out how to specialize our container classes for object
: For all the container methods returning references to items (in this case a reference to an object
's pointer), Swig generates a wrapper code which fails to compile due to an invalid dynamic_cast (basically it tries to cast object **
into Swig::Director *
)
I managed to reproduce the issue with the following code.
Test.h
#ifndef TEST_H
#define TEST_H
template< typename T >
class Vector
{
public:
inline Vector(void)
: m_Data(nullptr)
, m_Size(0)
{
}
inline ~Vector(void)
{
delete [] m_Data;
}
inline void add(const T & item)
{
T * data = new T [m_Size + 1];
for (int i = 0; i < m_Size; ++i)
{
data[i] = std::move(m_Data[i]);
}
delete [] m_Data;
m_Data = data;
m_Data[m_Size++] = item;
}
inline const T& item(int index) const
{
return m_Data[index];
}
inline int count(void) const
{
return m_Size;
}
private:
T * m_Data;
int m_Size;
};
class Foo
{
public:
Foo(void) = default;
virtual ~Foo(void) = default;
virtual const char * method(void) const
{
return "Foo::method";
}
};
class Cache
{
public:
static void add(Foo * item = nullptr)
{
m_Cache.add(item == nullptr ? new Foo() : item);
}
static const Vector< Foo * > & get(void)
{
return m_Cache;
}
static Foo * get(int index)
{
return m_Cache.item(index);
}
private:
static Vector< Foo * > m_Cache;
};
Vector< Foo * > Cache::m_Cache;
#endif // TEST_H
core.i
%module(directors="1") core
// we want to be able to inherit Foo in Python
%feature("director") Foo;
// generate wrappers
%include "Test.h"
// specialize Vector for Foo
%template(FooVector) Vector<Foo*>;
// when compiling the wrapper code, include those
%{
#include "Test.h"
%}
If you generate the Python module (swig.exe -python -c++ core.i
) it works fine, but the generated core_wrap.cxx
file fails to build because the generated wrapper code for Vector::item
contains an invalid dynamic_cast from Foo **
to Swig::Director *
The offending line is (where result is of type Foo **
)
director = SWIG_DIRECTOR_CAST(result);
And if I manually fix it like this:
director = SWIG_DIRECTOR_CAST(*result);
Then the module compiles correctly, and everything works fine.
So basically my question is: is this a bug in Swig ? Am I doing things wrong ? Is there a workaround to tell Swig to correctly dereference my Foo **
result before casting to Swig::Director *
?
Any help appreciated :)
I found a solution to your problem.
In some situations, using the director feature and native RTTI leads to code, which does not compile out of the box, e.g. when using distutils
from Python.
A solution, which works for your example is to define SWIG_DIRECTOR_NORTTI
when compiling the code, e.g. for the GNU compiler add -DSWIG_DIRECTOR_NORTTI
to the CXXFLAGS
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments