After reading an excellent answer on Dynamically rethrowing self-defined C++ exceptions as Python exceptions using SWIG, I am trying to throw a custom Exception from C++ and catch it in Python. I have tried to build the simplest example, so that I can see what I'm doing wrong. I would appreciate some help here.
I've started by creating a class called Example which has one method. In this method, I always throw my Exception which extends the Exception base class in C++. This exception is declared in the header.
I'm trying to catch this Exception in Python but so far I am unable to get this to compile. I tried some of the other solutions in the thread mentioned aboved, and while they compiled, I did not seem to be able to catch the Exception without Python aborting.
Here's what I have so far (a very basic project)
example.h
#ifndef EXAMPLE_H
#define EXAMPLE_H
#include <string>
#include <exception>
class Example
{
public:
std::string getName();
};
class ExampleException
{
public:
ExampleException(const std::string &what) { this->eMsg == (std::string(what)); }
const char * what() const throw() { return eMsg.c_str(); }
private:
std::string eMsg;
};
#endif // EXAMPLE_H
example.cpp
#include "example.h"
#include "exception"
using namespace std;
std::string Example::getName()
{
/* Always throw an exception just so we can test this */
throw ExampleException("Couldn't find a name");
return("John");
}
example.i
%module example
%include "example.i"
%include exception.i
%init %{
m_ExampleException = PyErr_NewException("_example.ExampleException", NULL, NULL);
Py_INCREF(m_ExampleException);
PyModule_AddObject(m, "ExampleException", m_ExampleException);
%}
%exception {
try {
$action
} catch (ExampleException &e) {
PyErr_SetString(ExampleException, const_cast<char*>(e.what()));
SWIG_fail;
}
}
%{
#include "example.h"
#define SWIG_FILE_WITH_INIT
static PyObject* m_ExampleException;
%}
test.py
import example
try:
print example.Example_getName()
except ExampleException as e:
print e.what()
And I run the following commands to build the project:
swig -verbose -python -c++ example.i
g++ -fPIC -c example_wrap.cxx -I/usr/include/python2.7 -o example_wrap.o -fPIC
g++ -c example.cpp -I/usr/include/python2.7 -fPIC
g++ -shared example_wrap.o example.o -o _example.so
Unfortunately, I am given the following error message as well as a warning:
example_wrap.cxx: In function ‘void init_example()’:
example_wrap.cxx:3839:82: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
m_ExampleException = PyErr_NewException("_example.ExampleException", NULL, NULL);
^
In file included from /usr/include/python2.7/Python.h:80:0,
from example_wrap.cxx:171:
/usr/include/python2.7/object.h:769:20: error: expected primary-expression before ‘)’ token
((PyObject*)(op))->ob_refcnt++)
I feel like I'm missing something obvious and would appreciate an extra pair of eyes. I have not used SWIG and C++ together extensively before.
Thanks for your time