[pypy-dev] okay to rename cppyy -> _cppyy
wlavrijsen at lbl.gov
wlavrijsen at lbl.gov
Thu Jul 20 21:17:47 EDT 2017
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 at lbl.gov -- +1 (510) 486 6411 -- www.lavrijsen.net
More information about the pypy-dev
mailing list