[C++-sig] Re: call_method
David Abrahams
dave at boost-consulting.com
Sun Nov 17 00:44:37 CET 2002
"Brett Calcott" <brett.calcott at paradise.net.nz> writes:
> 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.
Let's try.
> Assumption: I have a c++ library and I want to layer the python stuff on top
> with minimal intrusion.
That's a Boost.Python design premise.
> 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.
Yup. You probably want a virtual destructor in agent.
> Now, what do I need to do to expose my C++ lib to python and make
> agent::do_something overrideable in python code?
Just the usual stuff. Make a py_agent class like this:
struct agent_callback : agent
{
agent_callback(PyObject* self) : m_self(self) {}
void do_something() { call_method<void>(self, "do_something"); }
// expose this as "do_something"
static void default_do_something(agent& a)
{ a.agent::do_something(); }
PyObject* m_self;
};
...
class<agent, agent_callback, ...>("agent")
.def("do_something", &agent_callback::default_do_something)
;
> 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
Why? How?
> - 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.
Shouldn't be neccessary.
> 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?
Yes, or at least it will once we make the right changes.
> Am I required to call it whenever I need to access the
> elements in m_agents?
No, why would you? Those are shared_ptr<agent>s.
> 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.
HTH,
--
David Abrahams
dave at boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution
More information about the Cplusplus-sig
mailing list