Swig - binding a method returning a reference to a pointer of a director class

Citron

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 :)

Jens Munk

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.

edited at
0

Comments

0 comments
Login to comment

Related