[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