
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 -- WLavrijsen@lbl.gov -- +1 (510) 486 6411 -- www.lavrijsen.net