[pypy-commit] pypy cppyy-packaging: initial support for function pointer arguments
wlav
pypy.commits at gmail.com
Thu Apr 26 13:34:09 EDT 2018
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: cppyy-packaging
Changeset: r94451:f8f27990a737
Date: 2018-04-25 16:59 -0700
http://bitbucket.org/pypy/pypy/changeset/f8f27990a737/
Log: initial support for function pointer arguments
diff --git a/pypy/module/_cppyy/capi/loadable_capi.py b/pypy/module/_cppyy/capi/loadable_capi.py
--- a/pypy/module/_cppyy/capi/loadable_capi.py
+++ b/pypy/module/_cppyy/capi/loadable_capi.py
@@ -421,7 +421,7 @@
_cdata_to_ptr(space, call_capi(space, 'function_address_from_index', args)))
def c_function_address_from_method(space, cppmethod):
return rffi.cast(C_FUNC_PTR,
- _cdata_to_ptr(space, call_capi(space, 'function_address_from_method', _ArgH(cppmethod))))
+ _cdata_to_ptr(space, call_capi(space, 'function_address_from_method', [_ArgH(cppmethod)])))
# handling of function argument buffer ---------------------------------------
def c_allocate_function_args(space, size):
diff --git a/pypy/module/_cppyy/converter.py b/pypy/module/_cppyy/converter.py
--- a/pypy/module/_cppyy/converter.py
+++ b/pypy/module/_cppyy/converter.py
@@ -686,6 +686,32 @@
decref(space, rffi.cast(PyObject, rffi.cast(rffi.VOIDPP, arg)[0]))
+class FunctionPointerConverter(TypeConverter):
+ def __init__(self, space, signature):
+ self.signature = signature
+
+ def convert_argument(self, space, w_obj, address, call_local):
+ # TODO: atm, does not actually get an overload, but a staticmethod
+ from pypy.module._cppyy.interp_cppyy import W_CPPOverload
+ cppol = space.interp_w(W_CPPOverload, w_obj)
+
+ # find the function with matching signature
+ for i in range(len(cppol.functions)):
+ m = cppol.functions[i]
+ if m.signature(False) == self.signature:
+ x = rffi.cast(rffi.VOIDPP, address)
+ x[0] = rffi.cast(rffi.VOIDP,
+ capi.c_function_address_from_method(space, m.cppmethod))
+ address = rffi.cast(capi.C_OBJECT, address)
+ ba = rffi.cast(rffi.CCHARP, address)
+ ba[capi.c_function_arg_typeoffset(space)] = 'p'
+ return
+
+ # lookup failed
+ raise oefmt(space.w_TypeError,
+ "no overload found matching %s", self.signature)
+
+
class MacroConverter(TypeConverter):
def from_memory(self, space, w_obj, w_pycppclass, offset):
# TODO: get the actual type info from somewhere ...
@@ -752,6 +778,9 @@
elif "(anonymous)" in name:
# special case: enum w/o a type name
return _converters["internal_enum_type_t"](space, default)
+ elif "(*)" in name or "::*)" in name:
+ # function pointer
+ return FunctionPointerConverter(space, name[name.find("*)")+2:])
# 5) void* or void converter (which fails on use)
if 0 <= compound.find('*'):
diff --git a/pypy/module/_cppyy/interp_cppyy.py b/pypy/module/_cppyy/interp_cppyy.py
--- a/pypy/module/_cppyy/interp_cppyy.py
+++ b/pypy/module/_cppyy/interp_cppyy.py
@@ -128,7 +128,7 @@
def register_class(space, w_pycppclass):
w_cppclass = space.findattr(w_pycppclass, space.newtext("__cppdecl__"))
- cppclass = space.interp_w(W_CPPClassDecl, w_cppclass, can_be_None=False)
+ cppclass = space.interp_w(W_CPPClassDecl, w_cppclass)
# add back-end specific method pythonizations (doing this on the wrapped
# class allows simple aliasing of methods)
capi.pythonize(space, cppclass.name, w_pycppclass)
@@ -195,7 +195,7 @@
@staticmethod
def unpack_cppthis(space, w_cppinstance, declaring_scope):
- cppinstance = space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=False)
+ cppinstance = space.interp_w(W_CPPInstance, w_cppinstance)
cppinstance._nullcheck()
return cppinstance.get_cppthis(declaring_scope)
@@ -442,7 +442,7 @@
class CPPFunction(CPPMethod):
- """Global (namespaced) function dispatcher."""
+ """Global (namespaced) / static function dispatcher."""
_immutable_ = True
@@ -807,7 +807,7 @@
def is_static_data(space, w_obj):
try:
- space.interp_w(W_CPPStaticData, w_obj, can_be_None=False)
+ space.interp_w(W_CPPStaticData, w_obj)
return space.w_True
except Exception:
return space.w_False
@@ -1183,7 +1183,7 @@
# scopes of the argument classes (TODO: implement that last option)
try:
# TODO: expecting w_other to be an W_CPPInstance is too limiting
- other = self.space.interp_w(W_CPPInstance, w_other, can_be_None=False)
+ other = self.space.interp_w(W_CPPInstance, w_other)
for name in ["", "__gnu_cxx", "__1"]:
nss = scope_byname(self.space, name)
meth_idx = capi.c_get_global_operator(
@@ -1205,7 +1205,7 @@
# fallback 2: direct pointer comparison (the class comparison is needed since
# the first data member in a struct and the struct have the same address)
- other = self.space.interp_w(W_CPPInstance, w_other, can_be_None=False) # TODO: factor out
+ other = self.space.interp_w(W_CPPInstance, w_other) # TODO: factor out
iseq = (self._rawobject == other._rawobject) and (self.clsdecl == other.clsdecl)
return self.space.newbool(iseq)
@@ -1322,7 +1322,7 @@
offset = capi.c_base_offset1(space, actual, clsdecl, rawobject, -1)
rawobject = capi.direct_ptradd(rawobject, offset)
w_cppdecl = space.findattr(w_pycppclass, space.newtext("__cppdecl__"))
- clsdecl = space.interp_w(W_CPPClassDecl, w_cppdecl, can_be_None=False)
+ clsdecl = space.interp_w(W_CPPClassDecl, w_cppdecl)
except Exception:
# failed to locate/build the derived class, so stick to the base (note
# that only get_pythonized_cppclass is expected to raise, so none of
@@ -1340,7 +1340,7 @@
# fresh creation
w_cppinstance = space.allocate_instance(W_CPPInstance, w_pycppclass)
- cppinstance = space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=False)
+ cppinstance = space.interp_w(W_CPPInstance, w_cppinstance)
cppinstance.__init__(space, clsdecl, rawobject, is_ref, python_owns)
memory_regulator.register(cppinstance)
return w_cppinstance
@@ -1368,7 +1368,7 @@
except Exception:
# accept integer value as address
rawobject = rffi.cast(capi.C_OBJECT, space.uint_w(w_obj))
- decl = space.interp_w(W_CPPClassDecl, w_clsdecl, can_be_None=False)
+ decl = space.interp_w(W_CPPClassDecl, w_clsdecl)
return wrap_cppinstance(space, rawobject, decl, python_owns=owns, do_cast=cast)
@unwrap_spec(owns=bool, cast=bool)
@@ -1384,7 +1384,7 @@
def move(space, w_obj):
"""Casts the given instance into an C++-style rvalue."""
- obj = space.interp_w(W_CPPInstance, w_obj, can_be_None=True)
+ obj = space.interp_w(W_CPPInstance, w_obj)
if obj:
obj.flags |= INSTANCE_FLAGS_IS_R_VALUE
return w_obj
diff --git a/pypy/module/_cppyy/test/test_datatypes.py b/pypy/module/_cppyy/test/test_datatypes.py
--- a/pypy/module/_cppyy/test/test_datatypes.py
+++ b/pypy/module/_cppyy/test/test_datatypes.py
@@ -764,4 +764,7 @@
raises(TypeError, f3, f1, 2, 3)
+ # TODO: get straightforward access to the overload type
+ f2 = cppyy.gbl.__cppdecl__.get_overload('sum_of_double')
+
assert 5. == f3(f2, 5., 0.)
More information about the pypy-commit
mailing list