Hi,

[replying to self]

And yes, it is technically possible to write a bindings generator that only
depends on LLVM during offline bindings generation, not at run-time. But
then you'd just have SWIG (albeit with a standards-compliant parser).

it hit me yesterday that instead of generating something offline for cppyy
to read, you could also use cppyy_backend directly to generate a pure python
module for use with cffi as it knows about sizes, offsets, name mangling,
class relations etc., etc., etc.

(The point is that cppyy_backend exposes a minimalistic C-API, which itself
can be bound with cffi, as _cppyy in fact does.)

(There are still wrappers needed for inlined functions, overloaded
operator new, virtual inheritance offsets, etc., but those could be stuffed
in a .cxx on the side of the cffi-based Python module. Can't solve automatic
template instantiation this way, though: cppyy will always be superior.)

So, I wrote a quick proof of concept (https://bitbucket.org/wlav/quaff/src):

 $ cat Simple.h
 class Simple {
 public:
     Simple();
     Simple(int);
     virtual ~Simple();

 public:
     int get_data();
     void set_data(int);

 private:
     int m_data;
 };

 $ cat Simple.cxx
 #include "Simple.h"

 Simple::Simple() : m_data(42) { }
 Simple::Simple(int i) : m_data(i) { }
 Simple::~Simple() { }

 int Simple::get_data() { return m_data; }
 void Simple::set_data(int i) { m_data = i; }

 $ g++ -shared -o libsimple.so -fPIC Simple.cxx

 $ python
 >>>> from quaff import generate
 >>>> generate.generate_class('simple', 'Simple', 'libsimple.so')
 >>>> import simple
 >>>> s1 = simple.Simple()
 >>>> s1.get_data()
 42
 >>>> s1.set_data(13)
 >>>> s1.get_data()
 13
 >>>> s2 = simple.Simple(99)
 >>>> s2.get_data()
 99
 >>>>

What quaff generated looks like this:

 $ cat simple.py
 from cffi import FFI

 _ffi = FFI()

 _ffi.cdef("""
 void _ZN6SimpleC1Ev(void*);
 void _ZN6SimpleC1Ei(void*, int);
 int _ZN6Simple8get_dataEv(void*);
 void _ZN6Simple8set_dataEi(void*, int);
 """)

 _dll = _ffi.dlopen('libsimple.so')

 class Simple(object):
   def __init__(self, *args):
     self._cpp_this = _ffi.new('char[]', 16)
     if len(args) == 0:
       _dll._ZN6SimpleC1Ev(self._cpp_this, *args)
     if len(args) == 1:
       _dll._ZN6SimpleC1Ei(self._cpp_this, *args)
   def get_data(self, *args):
     return _dll._ZN6Simple8get_dataEv(self._cpp_this, *args)
   def set_data(self, *args):
     return _dll._ZN6Simple8set_dataEi(self._cpp_this, *args)

which is nicely standalone for distribution (yes, the result is platform
specific, but no more so than a binary .so and way better than a Python
extension module).

Best regards,
           Wim
--
wlavrij...@lbl.gov    --    +1 (510) 486 6411    --    www.lavrijsen.net
_______________________________________________
pypy-dev mailing list
pypy-dev@python.org
https://mail.python.org/mailman/listinfo/pypy-dev

Reply via email to