I am unsure on how best to tackle it.
I have a C++ framework which makes use of inheritance and virtual
method. something like this:
// an instance implementing IAlgorithm is initialized once and then
// process data multiple times via 'execute' and gets a chance
// at producing some statistics once w/ 'finalize'
class IAlgorithm
{
public:
virtual int execute() = 0;
};
the application driver is then doing something like that:
StatusCode AppMgr::run()
{
typedef std::vector<IAlgorithm*>::iterator Itr_t;
for (Itr_t
itr = this->m_algs.begin(),
iend = this->m_algs.end();
itr != iend;
++itr) {
int sc = (*itr)->execute();
if (sc) {/*handle error*/}
}
}
// EOF
now, I'd like to provide users with the ability to implement their own
algorithms in cython.
AFAIK, it isn't possible (yet?) to inherit from a C++ class in cython
code neither it is to hope that proper redirections of method calls will
work.
so my plan was to have a little C++ wrapper class like that:
typedef int (*ExecFct_t)(void* obj);
class CyAlgBase : public IAlgorithm
{
public:
void* m_cy_obj;
ExecFct_t m_cy_fct;
void set_cy_state(void *cy_obj, ExecFct_t cy_fct)
{this->m_cy_obj = cy_obj; this->m_cy_fct = cy_fct;}
virtual int execute() { this->m_cy_fct(this->m_cy_obj); }
};
and have, on the cython side:
##
cdef extern from "CyAlgBase.h":
cdef cppclass CyAlgBase:
# ...
cdef class AlgBase:
cdef int execute(self):
print("AlgBase.execute!")
cdef int cy_fct_execute(void *obj):
cdef AlgBase alg = <AlgBase>(obj)
return alg.execute()
cdef public api IAlgorithm* create_alg(char* cls_name):
cdef CyAlgBase* alg = new CyAlgBase()
cdef AlgBase cy_alg = create_user_alg_from(cls_name)
alg.set_cy_state(<void*>cy_alg, <ExecFct_t>cy_fct_execute)
return <IAlgorithm*>alg
## EOF
then users would just have to inherit from AlgBase and implement their
own 'execute' method.
well, that's the plan (with the goal to by-pass most of the python C-API
overhead...)
anything doomed to fail ? (ref-counting ?)
anything which could be done better ?
cheers,
sebastien.
--
#########################################
# Dr. Sebastien Binet
# Laboratoire de l'Accelerateur Lineaire
# Universite Paris-Sud XI
# Batiment 200
# 91898 Orsay
#########################################
That is correct.
This method should work well, but you do need to manually do the
recounting. Specifically, do a PyIncref in set_cy_state (possibly with
a decref as well, if it's holding onto an old one), and of course
decref within the destructor. To simplify, it might make sense to take
the object pointer (I'd call it a PyObject* rather than a void*) in
the construtor, performing the incref there, and then put the decref
in the destructor, making it easy to get the refcounting correct by
tying it to the lifetime of the C++ instance.
When you get this working, I think it would be valuable example code
for others to put up on the wiki.
- Robert
On Fri, 19 Nov 2010 11:54:21 -0800, Robert Bradshaw <robe...@math.washington.edu> wrote:
> > well, that's the plan (with the goal to by-pass most of the python C-API
> > overhead...)
> >
> > anything doomed to fail ? (ref-counting ?)
> > anything which could be done better ?
>
> This method should work well, but you do need to manually do the
> recounting. Specifically, do a PyIncref in set_cy_state (possibly with
> a decref as well, if it's holding onto an old one), and of course
> decref within the destructor. To simplify, it might make sense to take
> the object pointer (I'd call it a PyObject* rather than a void*) in
> the construtor, performing the incref there, and then put the decref
> in the destructor, making it easy to get the refcounting correct by
> tying it to the lifetime of the C++ instance.
>
> When you get this working, I think it would be valuable example code
> for others to put up on the wiki.
here it is:
http://bitbucket.org/binet/cy-cxxfwk/src
hth,
sebastien.
You mean that the C++ class has a virtual method, and that when
arbitrary C++ code calls that virtual method then Python code should be
executed?
I'm not sure if that is possible...AFAIK we don't ever generate C++
classes or even allow subclassing a C++ class in Cython.
Dag Sverre
this involves quite some scaffolding and it seems to me it could
theoretically be automated.
cheers,
sebastien.
OK, please pardon my laziness in this case.
Dag Sverre