[C++-sig] call_method

Brett Calcott brett.calcott at paradise.net.nz
Sat Nov 9 02:08:21 CET 2002


Hi all,

(Sorry for the delay in getting back David)

> Have you tried adding a call to
>
>    implicitly_convertible<py_agent_ptr,agent_ptr>()
>

Damn. I Should have found that really...
It works fine now. Yay!

However, the example I hacked up displays a weird bug. The virtual function
returns a char const *, and when I subclass this in python and return a
string it throws an error:

ReferenceError: Attempt to return dangling pointer to object of type: char
V:/src/boost_python_test/test>python test.py

...but only if there is a space in the string returned. This must be some
weird side effect. Or returning a char const * from python may just be plain
dodgy. Anyway I thought you might want to know about it.
Note: VC6 SP5 - XP Professional.
Here's the code:

namespace {

   class agent
   {
   public:
      agent()
      {
      }

      virtual char const *do_something() const
      {
         return "agent";
      }

      virtual ~agent()
      {
      }
   };

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

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

      char const *do_something() const
      {
         using namespace boost::python;
         return call_method<char const*>(m_self, "do_something");
      }

      PyObject* const m_self;

   };
   typedef boost::shared_ptr<py_agent> py_agent_ptr;

   class engine
   {
   public:
      engine() {}

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

      agents m_agents;
   };

}

BOOST_PYTHON_MODULE(simple)
{
   using namespace boost::python;
   implicitly_convertible<py_agent_ptr,agent_ptr>();


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

   class_<agent, bases<>, agent_ptr>("agent")
      .def("do_something", &agent::do_something)
      ;

    class_<agent, bases<>, py_agent_ptr, boost::noncopyable>("py_agent")
        .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<>()))
      ;

}


and the python:

import simple

e = simple.engine()

class my_agent(simple.py_agent):
    def do_something(self):
        # return "my agent here" ******CRASH****
        return "my_agent_here" # this is okay

a1 = simple.agent()
a2 = my_agent()

e.add_agent(a1)
e.add_agent(a2)

for a in e.agents:
    print a.do_something()


Cheers,
Brett






More information about the Cplusplus-sig mailing list