Hi all,
It has been easier than I thought until now (so thank you very much to the Cython devteam) but I met some problems with a piece of code which requires me to wrap boost::bind()...
So I have created a minimal test code which mimic the original code:
- lets say bind.h and bind.cpp is the code of the library I am trying to wrap. You can build with the following command:
$ clang++ -std=c++11 -Wall -pedantic -I<PATH TO BOOST INCLUDES> bind.cpp -o bind
(g++ should work too !)
And hopefully it should work :
$ ./bind
(void*)argv: 0x7fff594f1b30
Hello from some_callback !
some_ptr: 0x7fff594f1b30
End of execution...
You can build a shared lib with this command:
$ clang++ -std=c++11 -Wall -pedantic -shared -I<PATH TO BOOST INCLUDES> bind.cpp -o libbind.so
- I wrote a Cython wrapper which almost compiles. See _bind_defs.pxd and _bind.pyx. This can be build with a setup.py like this:
from distutils.core import setup, Extension
from Cython.Build import cythonize
ext = Extension("_bind",
sources=["_bind.pyx"],
include_dirs=["<PATH TO BOOST INCLUDES>"],
libraries=["bind"],
library_dirs=["<PATH TO libbind.so>"],
language="c++")
setup(name="_bind", ext_modules=cythonize(ext))
I build with the usual command:
$ python setup.py build_ext
But I got 2 errors:
_bind.cpp:763:17: error: elaborated type refers to a template
struct boost::arg __pyx_v__1;
^
/Users/bu2/.brew/include/boost/bind/arg.hpp:29:26: note: declared here
template< int I > struct arg
^
1 error generated.
(please don't shout at me)
I did not find a better way than to fix the generated code manually, replacing boost::arg by boost::arg<1> (see boost/bind/placesholders.hpp and boost/bind/arg.hpp, it seems to me that Cython can not wrap code such as: template<int i> class arg {} ).
_bind.cpp:776:22: error: call to 'bind' is ambiguous
__pyx_v_callback = boost::bind<__pyx_t_10_bind_defs_callback_t>(__pyx_f_5_bind_some_callback, __pyx_v__1);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/bu2/.brew/include/boost/bind/bind.hpp:1811:5: note: candidate function [with R = void (void *), F = void (*)(void *), A1 = boost::arg<1>]
BOOST_BIND(F f, A1 a1)
^
/Users/bu2/.brew/include/boost/bind/bind.hpp:1796:20: note: expanded from macro 'BOOST_BIND'
#define BOOST_BIND bind
^
/Users/bu2/.brew/include/boost/bind/bind.hpp:1977:5: note: candidate function [with F = void (void *), A1 = boost::arg<1>]
BOOST_BIND(F f, A1 a1)
^
/Users/bu2/.brew/include/boost/bind/bind.hpp:1796:20: note: expanded from macro 'BOOST_BIND'
#define BOOST_BIND bind
^
1 error generated.
Once again, I can fix it manually by replacing boost::bind<__pyx_t_10_bind_defs_callback_t> by boost::bind. In my wrapper code I had to introduce the T template parameter but I could not find the C++ trick (in boost/bind implementation) that allows us to call boost::bind() without specifying template parameters...
Then it builds successfully.
I hope there is a better way to handle those 2 cases but I have been searching for days without luck. Otherwise sed will do it :-)
Best Regards,
Bruno Le Hyaric.