[C++-sig] Re: call_method

Brett Calcott brett.calcott at paradise.net.nz
Sun Nov 17 00:42:57 CET 2002


>
> No, that's my point: we can do it /no matter how the T is held/.
>
> First imagine using handle<> as the 'other shared ptr' . Then you
> can easily replace it with PyObject* :
>
> struct pyobject_deleter
> {
>     pyobject_deleter(handle<> p): p_(p)
>     {
>     }
>
>     void operator()(void const *)
>     {
>         p_.reset();
>     }
> private:
>     handle<> p_;
> };
>
> template <class T>
> shared_ptr<T> make_shared(PyObject* p)
> {
>     extract<T*> x(p);
>     if (x)
>     {
>         return shared_ptr<T> px(x(),
pyobject_deleter(handle<>(borrowed(p)))));
>     }
>     else
>     {
>         // conversion failed
>     }
> }
>
>

Ok, make_shared() increments the PyObject refcount, and the pyobject deleter
decrements it. But I still don't get the full picture -- can I put this back
in the context of my project.

Assumption: I have a c++ library and I want to layer the python stuff on top
with minimal intrusion.

It looks like this:

class agent
{
public:
    virtual void do_something()
    {
       cout << "in c++";
    }
};
typedef shared_ptr<agent> agent_ptr;
typedef vector<agent_ptr> agents;

class engine
{
    agents m_agents;
public:
    void add_agent(agent_ptr const &a)
    {
        m_agents.push_back(a);
    }

    void do_stuff_with_agents()
    {
        for_each(m_agents.begin(), m_agents.end(),
mem_fun(agent::do_something));
    }
};

Note that I am using shared_ptr here for my own purpose *unrelated* to
python implementation.

Now, what do I need to do to expose my C++ lib to python and make
agent::do_something overrideable in python code?

in python I want:

from xxxx import *
class py_agent(agent):
   def do_something():
      print 'in python'

e = engine()
e.add_agent(agent())
e.add_agent(py_agent())
e.do_stuff_with_agents()

It seems I have to touch the source code - so we are intruding on the c++
lib. Not the best, but unavoidable in this situation I think. The 'crazy
pointer' solution required inheriting agent from a base class and adding a
constructor with PyObject *. But we can easily use some #ifdef's to compile
a pythonized-or-not version of the library.

Now the solution that you are proposing requires a call to make_shared. I'm
not sure where this is happening. Does Boost.Python do it for me? Am I
required to call it whenever I need to access the elements in m_agents? I
can't see how the solution you have can work without causing me to change
significantly the underlying c++ lib. Maybe I just don't get it yet.

Cheers,
Brett


















More information about the Cplusplus-sig mailing list