Author: Wim Lavrijsen <wlavrij...@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.) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit