[C++-sig] Help With Embedded Pure Virtual Classes
Matt
mjkeyes at sbcglobal.net
Sat Oct 8 19:05:23 CEST 2005
Hey all,
(there is quite some code below... my apologies in advance, but there should
be a fairly simple solution to this question I'm sure)
My apologies for spamming the mailing list lately... i'm just trying to get
off to a good start working with embedding Python in C//C++. (Thanks to
Ralf thus far for his help, too!)
Anyways, here's my current problem. i am finally able to get an instance of
a class derived in Python from a pure virtual class in C++ created.
However, i am not able to call any of the pure virtual methods. One of the
base classes from the intermediate "wrapper" class is the
boost::python::wrapper class, but it's own internal object never gets set
(and i don't think there is a way to manually set it since it is a private
variable).
Here is some of my code:
/***********************************************************/
//Base pure class:
template<class commandtype>
class InputHandler
{
//Pure Functions
public:
virtual commandtype HandleInput(const commandtype &Input) = 0;
virtual commandtype Enter() = 0;
virtual commandtype Leave() = 0;
virtual commandtype Hungup() = 0;
virtual commandtype Flooded() = 0;
virtual commandtype NoRoom() = 0;
//End Pure Functions
/*...*/
};
//Intermediate class:
class PythonInputHandler : public InputHandler<std::string>, public
wrapper<InputHandler<std::string> >
{
public:
PythonInputHandler(PyObject *pSelf = NULL) : m_Self(pSelf) {}
PythonInputHandler(PyObject *pSelf, const InputHandler<std::string> &rhs) :
InputHandler<std::string>(rhs) , m_Self(pSelf) {}
virtual ~PythonInputHandler() {}
std::string HandleInput(const std::string &Input)
{
const char *p = ""; //note, std::string always causes heap error, so use
char
try
{
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // Workaround for vc6/vc7
p = call<char*>(this->get_override("HandleInput").ptr(), Input.c_str());
#else
p = this->get_override("HandleInput")(Input);
#endif
}
catch(...)
{
PyErr_Print();
p = "";
}
return (p != NULL ? p : "");
}
/*..other overriden pure methods...*/
};
//NOTE, SORRY AT THIS POINT I HAVE TO DOUBLESPACE EVERYTHING
//BECAUSE MY NEWSGROUP READER WANTS TO WRAP EVERYTHING IN ONE LINE
BOOST_PYTHON_MODULE(PyInputHandler)
{
class_<InputHandler<std::string>,PythonLib::PythonInputHandler,boost::noncopyable>("PythonInputHandler")
.def("HandleInput", pure_virtual(&InputHandler<std::string>::HandleInput))
/*...other exposed pure methods...*/
;
}
//Python code:
from PyInputHandler import *
class PyLogonHandler(PythonInputHandler):
def HandleInput(self,Input):
if Input == "/quit":
self.Quit()
elif Input == "/shutdown":
self.ShutDown()
else:
return Input
#other expose methods...
//Code to instantiate the object in C++:
try
{
handle<> hModulePtr(PyImport_ImportModule( "MyModule" ));
handle<> hNamespace(borrowed(PyModule_GetDict(hModulePtr.get())));
handle<> hClassPtr(PyRun_String("PyLogonHandler", Py_eval_input,
hNamespace.get(), hNamespace.get()));
object oClass(hClassPtr);
PyErr_Print();
object oHandler = oClass();
PythonLib::PythonInputHandler *pHandler =
extract<PythonLib::PythonInputHandler*>(oHandler);
m_Obj.push(oHandler); //so the object doesn't destruct itself after this is
finished (making the pointer invalid)
AddInputHandler(pHandler);
pHandler->HandleInput("testing");
}
catch(...)
{
PyErr_Print();
}
/***********************************************************/
Now then, everything works great. However, when I call the pure functions
from C++, the following occurs:
//code from above in PythonInputHandler
std::string HandleInput(const std::string &Input)
{
const char *p = ""; //note, std::string always causes heap error, so use
char
try
{
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // Workaround for vc6/vc7
p = call<char*>(this->get_override("HandleInput").ptr(), Input.c_str());
#else
p = this->get_override("HandleInput")(Input); //THROWS EXCEPTION BECAUSE
INTERNAL OBJECT IS NULL
#endif
}
catch(...)
{
PyErr_Print();
p = "";
}
I can't seem to get the internal wrapper's internal object (representing the
acutal Python class) set. I'm sure I'm missing something simple, but I'm
having difficulty tracking it down (and I can't find any tutorials that tie
all this together in a way that will allow me to do what I'm trying to do).
Thanks in advance!!
Matt
More information about the Cplusplus-sig
mailing list