How to pass Python function to a C++ class constructor and wrap it all up with Cython?

270 views
Skip to first unread message

GoFaster

unread,
Sep 20, 2016, 1:49:08 AM9/20/16
to cython-users
I've created this functional demo of a Cython wrapped C++ class. It demonstrates converting a python list to a std::vector and also how to callback a  Python function. It was inspired by the cheesefinder demo.

I would like to modify FruitJuicer.h to permit passing a Python function to the C++ FruitJuicer class constructor and store its function pointer-or-reference-or-whatever as a class variable at instantiation.

Problem is I can't seem to work out how to do this and get it wrapped by Cython.  In fact I don't even know if it's possible.

Can anyone please explain how to accomplish this?

Thanks,

GoFaster


Robert Bradshaw

unread,
Sep 20, 2016, 11:59:58 AM9/20/16
to cython...@googlegroups.com
You can do this exactly the same as with the cheesefinder example. The
only thing you need to be careful of is that the Python object (f in
that case) doesn't go out of scope and get garbage collected before
you're done with the C++ class using it.
Message has been deleted

Chris Barker

unread,
Sep 21, 2016, 4:17:14 PM9/21/16
to cython-users
On Tue, Sep 20, 2016 at 9:35 AM, GoFaster <sjgwe...@gmail.com> wrote:
If I try for example;

  1. def __cinit__(self, callback cb, list fruits_list):
  2.         self.ptr_cpp_juicer = new FruitJuicer(cb, fruits_list)

Then I get the error that 'callback' is not a recognised type.

If I try:

  1. def __cinit__(self, object cb, list fruits_list):
  2.         self.ptr_cpp_juicer = new FruitJuicer(cb, fruits_list)
Then I get the error that 'object' cannot be converted to 'pyFunc'.

Just guessing, but try this:

  1. def __cinit__(self, pyFunc cb, list fruits_list):
  2.         self.ptr_cpp_juicer = new FruitJuicer(cb, fruits_list)
 
I'm a new user of Cython and this is proving a challenge.

You are doing some quite challenging stuff here! You'll get it soon :-)

-CHB




--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris....@noaa.gov

GoFaster

unread,
Sep 26, 2016, 7:57:58 AM9/26/16
to cython-users
If it should be of interest to anyone I've created this simple functional example; FruitJuicer to demonstrate wrapping a C++ class with Cython. 
Amongst other things it demonstrates callbacks and bidirectional passing of a Python list to a std::vector<std::string> and executing a callback from a different C++ thread.

Though it's not directly on topic for the Cython mailing list; does anyone know how the Python Global Interpreter Lock (GIL) can be acquired and released from WITHIN a C++ thread?  I.e. in this case from FruitJuicer;

//Runs in a thread and performs callback to Python passing std::vector<std::string> to be converted to a Python list.
void run_juicer()
 {
 AcquireGILHere()
 pyVectorFunction(fruits, usrData);
 ReleaseGILHere()
 count += fruits.size();//keep count
 }

Ultimately I intend to use this pattern with a long running thread and would not want to hold the GIL indefinitely, just when there is Python work to do.

Thanks,

Gofaster
Reply all
Reply to author
Forward
0 new messages