SWIG with preprocessor macro from boost preprocessor
Question: I'm utilizing the enum with ToString implementation that was suggested here:
[How to convert an enum type variable to a
string?](http://stackoverflow.com/questions/5093460/how-to-convert-an-enum-
type-variable-to-a-string) It utilizes and works fine as far as I can tell.

My issues arise when I try to wrap and export the macro to a Python library
wrapped with SWIG. Similar question: [SWIG errors because of preprocessor
directive](http://stackoverflow.com/questions/10760287/swig-errors-because-of-
preprocessor-directive) There, the solution was to add headers / declarations
to the SWIG interface. I haven't had success with this so far. Chances are
that I just don't know what I have to add.

Tried:

    
    
    %include <boost/preprocessor/config/config.hpp>
    %include <boost/preprocessor/stringize.hpp>
    %include <boost/preprocessor/seq/for_each.hpp>
    %include <boost/preprocessor/seq/enum.hpp>
    

MWE:

minimal.h

    
    
    #ifndef MINIMAL_H
    #define MINIMAL_H
    #include <boost/preprocessor.hpp>
    
    //Found this here: http://stackoverflow.com/questions/5093460/how-to-convert-an-enum-type-variable-to-a-string
    
    #define X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOSTRING_CASE(r, data, elem)    \
        case elem : return BOOST_PP_STRINGIZE(elem);
    
    #define DEFINE_ENUM_WITH_STRING_CONVERSIONS(name, enumerators)                \
        enum name {                                                               \
            BOOST_PP_SEQ_ENUM(enumerators)                                        \
        };                                                                        \
                                                                                  \
        inline const char* ToString(name v)                                       \
        {                                                                         \
            switch (v)                                                            \
            {                                                                     \
                BOOST_PP_SEQ_FOR_EACH(                                            \
                    X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOSTRING_CASE,          \
                    name,                                                         \
                    enumerators                                                   \
                )                                                                 \
                default: return "[Unknown " BOOST_PP_STRINGIZE(name) "]";         \
            }                                                                     \
        }
    
    DEFINE_ENUM_WITH_STRING_CONVERSIONS(my_enum, (A)(B))
    #endif
    

minimal.cpp

    
    
    #include <iostream> 
    #include "minimal.h"
    
    int main(){
        using namespace std;
        cout << A << ": " << ToString(A) << endl;
        cout << B << ": " << ToString(B) << endl;
    
    }
    

minimal.i

    
    
    %module minimal
    %{
    #include "minimal.h"
    %}
    %include "minimal.h"
    

The error is not very indicative. Line 29 is the actual definition of my_enum.

    
    
    matthias@rp3deb:~/dvl/swig_boost_minimal$ swig minimal.i
    minimal.h:29: Error: Syntax error in input(1).
    

Any advice on how I could wrap this?


Answer: If you wanted to make SWIG read boost/preprocessor.hpp you'd do that with:

    
    
    %module minimal
    %{
    #include "minimal.h"
    %}
    %include <boost/preprocessor.hpp>
    %include "minimal.h"
    

Since by default SWIG doesn't follow `#include` directives. (You could also
use `-includeall` to make it follow them instead). In this case though I think
making the SWIG preprocessor make any kind of sense of the crazy magic that
the Boost preprocessor library uses is a lost cause.

Instead though we can try to get something with equally nice, but "Pythonic"
syntax instead. In esscence what we're going to do is write a totally
different version of `DEFINE_ENUM_WITH_STRING_CONVERSIONS` for SWIG wrappers
only. It will be compatible with the definitions seen by C++ though.

To do this I'm going to start by splitting your file minimal.h into two files.
One with the macro definition and one that uses it. (We could have done this
different ways, for example by wrapping the macro definitions with `#ifndef
DEFINE_ENUM_WITH_STRING_CONVERSIONS` or `#ifndef SWIG`, which would be equally
valid solutions).

Thus we now have enum.hh:

    
    
    #ifndef ENUM_H
    #define ENUM_H
    #include <boost/preprocessor.hpp>
    
    //Found this here: http://stackoverflow.com/questions/5093460/how-to-convert-an-enum-type-variable-to-a-string
    #define X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOSTRING_CASE(r, data, elem)    \
        case elem : return BOOST_PP_STRINGIZE(elem);
    
    #define DEFINE_ENUM_WITH_STRING_CONVERSIONS(name, enumerators)                \
        enum name {                                                               \
            BOOST_PP_SEQ_ENUM(enumerators)                                        \
        };                                                                        \
                                                                                  \
        inline const char* ToString(name v)                                       \
        {                                                                         \
            switch (v)                                                            \
            {                                                                     \
                BOOST_PP_SEQ_FOR_EACH(                                            \
                    X_DEFINE_ENUM_WITH_STRING_CONVERSIONS_TOSTRING_CASE,          \
                    name,                                                         \
                    enumerators                                                   \
                )                                                                 \
                default: return "[Unknown " BOOST_PP_STRINGIZE(name) "]";         \
            }                                                                     \
        }
    #endif
    

And minimal.h:

    
    
    #ifndef MINIMAL_H
    #define MINIMAL_H
    #include "enum.h"
    
    DEFINE_ENUM_WITH_STRING_CONVERSIONS(my_enum, (A)(B))
    #endif
    

So your minimal.cpp continues to work as before, but now we can write a SWIG
module that at least compiles, even if it doesn't do anything useful yet:

    
    
    %module minimal
    %{
    #include "minimal.h"
    %}
    %define DEFINE_ENUM_WITH_STRING_CONVERSIONS(name,enumerators)
    %enddef
    %include "minimal.h"
    

This currently has a stub, SWIG specific macro that we're going to fill out.
It's a little ugly how I've done this, simply because I'm trying to avoid
changing the way the existing macro is defined/used at all.

What I produced as a starting point is another file, enum.i:

    
    
    %include <std_vector.i>
    %include <std_string.i>
    
    %{
    #include <vector>
    #include <string>
    #include <tuple>
    %}
    
    %define DEFINE_ENUM_WITH_STRING_CONVERSIONS(name,enumerators)
    %{
      typedef std::tuple<name,std::string> name ## _entry;
      struct name ## _helper {
        std::vector<name ## _entry> list;
        name ## _helper(const name value) {
          list.push_back(std::make_tuple(value,ToString(value)));
        }
        name ## _helper operator()(const name value) {
          list.push_back(std::make_tuple(value,ToString(value)));
          return *this;
        }
      };
    
      static const std::vector<name ## _entry> name ## _list = name ## _helper enumerators . list;
    %}
    
    struct name ## _entry {
      %extend {
        const unsigned long value {
          return std::get<0>(*$self);
        }
        const std::string& label {
          return std::get<1>(*$self);
        }
      }
    };
    
    %template(name ## vec) std::vector<name ## _entry>;
    
    const std::vector<name ## _entry> name ## _list;
    
    %enddef
    

Such that minimal.i just needs to become:

    
    
    %module minimal
    
    %{
    #include "minimal.h"
    %}
    
    %include "enum.i"
    %include "minimal.h"
    

All that macro does is take the value of `enumerators`, which is going to be
something like `(A)(B)` and generate some code that's completely standard (if
quirky) C++ that expands this into a
`std::vector<std::tuple<my_enum,std::string>>`. That's done by mapping the
first enum member onto a constructor call, and the rest onto an overloaded
`operator()`. We use the `ToString()` supplied by enum.h to find the string
representation. Finally our macro has enough information to wrap the vector of
tuples in a way which makes sense from within Python.

With this in place we can do something like:

    
    
    import minimal
    print ", ".join(("%s(%d)" % (x.label,x.value) for x in minimal.my_enum_list))
    

Which, when compiled and run gives:

    
    
    A(0), B(1)
    

I.e. enough to start writing Python code that's aware of both the label and
the value of a C++ enum.

But let's not stop there! Why did I deliberately call the resulting vector
`my_enum_list` instead of just `my_enum`? Because there's more we can do now.

Python 2.7 doesn't have any default "enum-ish", but that doesn't prevent us
from wrapping this as something both Pythonic and natural to people who know
about enums. I made my Python 2.7 enum support by reading [this other
answer](http://stackoverflow.com/a/1695250/168175). To start with I added some
generic enum support routines to the file using `%pythoncode`, (labelled #1 in
final source) but outside the SWIG macro since there's no need to vary it. I
also added a `%pythoncode` inside the SWIG macro (labelled #2) that invokes
this once per actual enum. In order to make this work I had to convert the
`const std::vector` from the previous version into a function so that it was
accessible in the right part of the generated Python. Finally I had to show
SWIG a forward declaration of the real enum, in order to persuade it to
actually accept that as an argument to functions. The final result is:

    
    
    %include <std_vector.i>
    %include <std_string.i>
    
    %{
    #include <vector>
    #include <string>
    #include <tuple>
    %}
    
    // #1
    %pythoncode %{
    class EnumValue(int):
      def __new__(cls,v,l):
        result = super(EnumValue,cls).__new__(cls,v)
        result._value = l
        return result
      def __str__(self):
        return self._value
    
    def make_enum(name,enums):
        return type(name, (), enums)
    %}
    
    %define DEFINE_ENUM_WITH_STRING_CONVERSIONS(name,enumerators)
    %{
      typedef std::tuple<name,std::string> name ## _entry;
      struct name ## _helper {
        std::vector<name ## _entry> list;
        name ## _helper(const name value) {
          list.push_back(std::make_tuple(value,ToString(value)));
        }
        name ## _helper operator()(const name value) {
          list.push_back(std::make_tuple(value,ToString(value)));
          return *this;
        }
      };
    
      static const std::vector<name ## _entry> name ## _list() {
        return name ## _helper enumerators . list;
      }
    %}
    
    struct name ## _entry {
      %extend {
        const unsigned long value {
          return std::get<0>(*$self);
        }
        const std::string& label {
          return std::get<1>(*$self);
        }
      }
    };
    
    %template(name ## vec) std::vector<name ## _entry>;
    
    const std::vector<name ## _entry> name ## _list();
    
    // #2
    %pythoncode %{
      name = make_enum('name', {x.label: EnumValue(x.value, x.label) for x in name ## _list()})
    %}
    
    enum name;
    
    %enddef
    

I added a function to minimal.i to prove it really does work:

    
    
    %module minimal
    
    %{
    #include "minimal.h"
    %}
    
    %include "enum.i"
    %include "minimal.h"
    
    %inline %{
      void foo(const my_enum& v) {
        std::cerr << "GOT: " << v << "\n";
      }
    %}
    

And finally test it with:

    
    
    import minimal
    print minimal.my_enum
    print minimal.my_enum.A
    print minimal.my_enum.B
    
    minimal.foo(minimal.my_enum.B)
    

Which you'll be pleased to see worked and resulted in:

    
    
    <class 'minimal.my_enum'>
    A
    B
    GOT: 1
    

If you're using Python 3 there's a possibly nicer way to [represent
enums](https://docs.python.org/3/library/enum.html#module-enum), but I'll
leave that as an exercise for the reader for now. You can obviously tweak the
Python 2.7 fake enums to your taste as well.

