4

I have a little bit of C++ that I want to make accessible in python.

DynamicArray.h:

#include <vector>
#include <stdexcept>

namespace mspace {

    template <class T>
    class DynamicArray {

        // lets piggyback on std::vector.
        std::vector<T> m_implementation;

    public:

        typedef std::vector::size_type size_type;
        typedef T& reference;
        typedef const T& const_reference;

        const_reference operator [](size_type i) const noexcept(false)
        {
            if (i >= m_implementation.size())
                throw std::out_of_range("Ouch i >= DynamicArray.size() ");
            return m_implementation[i];
        }

        reference operator[](size_type i) noexcept(false)
        {
            if (i >= m_implementation.size())
                throw std::out_of_range("Ouch i >= DynamicArray.size() ");
            return m_implementation[i];
        }
    };
}

The problem is that I use operator[] and swig tells me: DynamicArray.h:25: Warning 389: operator[] ignored (consider using %extend). Ok apparently swig has good reasons that it cannot automatically wrap the mspace::DynamicArray::operator[] I get the warning once for the const and regular version. What I'm actually doing, like swig suggests, is include an extra file where I extend the dynamic array and once I can see it works in python, then I want to silence the warning.

Let pretend I've actually extended the DynamicArray. TI currently have something less verbose than this, but no matter what I try, I keep having the warning message. My interface file array.i:

%module mspace;

%{
#include "DynamicArray.h"
%}

%include "exception.i"

%warnfilter (389) DynamicArray::operator[] const;
%warnfilter (389) DynamicArray::operator[] ;

%warnfilter (389) DynamicArray<int>::operator[] const;
%warnfilter (389) DynamicArray<int>::operator[] ;

%warnfilter (389) mspace::DynamicArray<int>::operator[] const;
%warnfilter (389) mspace::DynamicArray<int>::operator[] ;

%include "DynamicArray.h"

%warnfilter (389) DynamicArray::operator[] const;
%warnfilter (389) DynamicArray::operator[] ;

%warnfilter (389) DynamicArray<int>::operator[] const;
%warnfilter (389) DynamicArray<int>::operator[] ;

%warnfilter (389) mspace::DynamicArray<int>::operator[] const;
%warnfilter (389) mspace::DynamicArray<int>::operator[] ;

%template (IntArray) mspace::DynamicArray<int>;

I run swig as: swig -python -c++ -Wall array.i or swig -python -builtin -c++ -Wall array.i

I'use swig 3.0.8 from the ubuntu-16.04 repositories.

I want to see the warnings, but also I want to remove the warnings when I've worked my way around them via extend. Has anyone any Idea what I'm missing. Because, I'm afraid that in my project I'm missing the warnings that I haven't worked around yet, because the list of these kinds of warnings keeps growing as my project grows.

hetepeperfan
  • 4,292
  • 1
  • 29
  • 47
  • Are you willing to alter the C++ header for SWIG (without changing its behavior for other use)? – Davis Herring Apr 12 '19 at 17:04
  • @DavisHerring I use the C++ header for C++ as well. So, if a solution a solution exists that uses `#ifdef SWIG ... #endif` swig exists, I might be willing. But the main goal is to be able to subscipt the DynamicArray in C++ and easily usable in as an IntArray in languages Swig supports. – hetepeperfan Apr 15 '19 at 07:09
  • It seems you’ve already hit on an answer, then—does it not work to `#ifdef` the `operator[]`s away and then use `%extend` to bring them back (under the Python names)? – Davis Herring Apr 15 '19 at 13:16
  • That works of course, but according to the docs http://www.swig.org/Doc3.0/Warnings.html#Warnings_suppression `%warnfilter` should also work, without polluting the c++ headerfiles with #ifdef... But sometimes one has to choose the lesser of two evils. Many false positive warnings are definitely evil, so perhaps that is best. – hetepeperfan Apr 15 '19 at 13:37
  • OK. You can either answer your own question in a few days—to help others who don’t know about `#ifdef SWIG` as a workaround—or edit it to preclude the answer. – Davis Herring Apr 15 '19 at 15:19

1 Answers1

0

As suggested by @Davis Herring in the comments below the questions. It is possible to use the preprocessor flags that swig uses like -DSWIG. Than you could use conditional compilation, or in the swig case, code generation. Perhaps this method is suboptimal, since you need to be able to alter the C++ header files.

#include <vector>
#include <stdexcept>

namespace mspace {

template <class T>
class DynamicArray {

    // lets piggyback on std::vector.
    std::vector<T> m_implementation;

public:

    typedef std::vector::size_type size_type;
    typedef T& reference;
    typedef const T& const_reference;

#ifndef SWIG
    const_reference operator [](size_type i) const noexcept(false)
    {
        if (i >= m_implementation.size())
            throw std::out_of_range("Ouch i >= DynamicArray.size() ");
        return m_implementation[i];
    }

    reference operator[](size_type i) noexcept(false)
    {
        if (i >= m_implementation.size())
            throw std::out_of_range("Ouch i >= DynamicArray.size() ");
        return m_implementation[i];
    }
#endif
};

}

This will work, because one can use %extend to implement getitem or use the python slots when using swig -c++ -python -builtin, however I would be very happy to mark an answer that uses warning suppression from the swig interface files. When the generated code is compiled, the a C++ compiler is used, so one can actually use the DynamicArray::operator[] from code inside the extensions. However, since not everyone can alter the C++ headers and to reduce code pollution by adding many #ifndefs SWIG in the code, I would be very happy to accept an answer that uses the suppression methods that swig provides for in the interface files.

hetepeperfan
  • 4,292
  • 1
  • 29
  • 47