[C++-sig] Help With Embedded Pure Virtual Classes
mjkeyes at sbcglobal.net
mjkeyes at sbcglobal.net
Mon Oct 10 12:45:10 CEST 2005
Easy fix:
BOOST_PYTHON_MODULE(PyInputHandler)
{
class_<InputHandler<std::string>,PythonLib::PythonInputHandler,boost::no
ncopyable>("PythonInputHandler")
.def("HandleInput",
pure_virtual(&InputHandler<std::string>::HandleInput))
/*...other exposed pure methods...*/
;
}
Should be:
BOOST_PYTHON_MODULE(PyInputHandler)
{
class_<PythonLib::PythonInputHandler,boost::noncopyable>("PythonInputHan
dler")
.def("HandleInput",
pure_virtual(&InputHandler<std::string>::HandleInput))
/*...other exposed pure methods...*/
;
}
"Matt" <mjkeyes at sbcglobal.net> wrote in message
news:<di8u7g$2fu$1 at sea.gmane.org>...
> 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