[C++-sig] call_method

Brett Calcott brett.calcott at paradise.net.nz
Thu Nov 7 12:01:09 CET 2002


Hi all,

Firstly, thanks for the funky library - Dave and others. I am looking
forward to making my development go a lot faster by scripting most of it and
leaving just the core in c++.

I somewhat overwhelmed by the sophistication of the methods involved to make
this thing work so elegantly - so I am grappling to understand how to make
it do what I want. (Likely that I should do what *it* wants..)

First up - a documentation bug (if you haven't already found it). I have the
download from boost.org - not CVS and I see this in call_method.html

// Callback class
class Base_callback : public Base
{
 public:
   Base_callback(PyObject* self) : m_self(self) {}

   char const* class_name() const { return call_method(m_self,
"class_name"); }
                                           ^^^^^^^^^^^^^^
   char const* Base_name() const { return Base::class_name(); }
 private:
   PyObject* const m_self;
};

That should be:
   char const* class_name() const { return call_method<char const*>(m_self,
"class_name"); }

Right? That had me fooled for a bit.

Now the problem:

class agent
{
public:
   virtual char const *do_something() const
   {
      return "something";
   }

   virtual ~agent() { }
};

typedef boost::shared_ptr<agent> agent_ptr;
typedef std::vector<agent_ptr> agents;

class engine
{
public:

   void add_agent(const agent_ptr &a)
   {
      m_agents.push_back(a);
   }

   agents m_agents;
};

BOOST_PYTHON_MODULE(pyengine)
{
   using namespace boost::python;

   class_<agents>("agents")
      .def("__iter__", iterator<agents>())
      ;

   class_<agent, bases<>, agent_ptr>("agent", init<const char *>())
      .def("name", &agent::name,
return_value_policy<copy_const_reference>())
      .def("do_something", &agent::do_something)
      ;

   class_<engine>("engine", init<>())
      .def("add_agent", &engine::add_agent)
      .add_property("agents"
        , make_getter(&engine::m_agents, return_internal_reference<>()))

      ;
}


This works fine as it is for creating engines and putting agents into it.
What I want to do now is have the option of creating a derived agent
"py_agent" which uses call_method() to allow python to "do_something".
However, I want both of these types to be in able to be put into the vector
of agents in the engine. To get this to work I need something like this I
think:

class py_agent : public agent
{
public:
   py_agent(PyObject* self = 0) : m_self(self) {}

   char const *do_something() const { return call_method<char
const*>(m_self, "do_something"); }

   PyObject* const m_self;

 };

But to use class_ on it I need to create another shared_ptr for the
py_agent,

typedef boost::shared_ptr<py_agent> py_agent_ptr;

and then this:

class_<agent, bases<>, py_agent_ptr, boost::noncopyable>("py_agent")
  .def("do_something", &py_agent::do_something)
   ;

But now, I can't add a py_agent using the python exported "add_agent"
function, as it is not the right type.


I am used to using shared_ptr in vectors for containing derived types - so,
as in this case, the engine can call "do_something" on all of them and they
can all "do their thing". How, if at all, can I get this happening here...


Cheers,
Brett


















More information about the Cplusplus-sig mailing list