[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