Author: Armin Rigo <ar...@tunes.org> Branch: py3.5 Changeset: r94506:e4a332215983 Date: 2018-05-09 18:55 +0200 http://bitbucket.org/pypy/pypy/changeset/e4a332215983/
Log: hg merge default diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -5,5 +5,16 @@ .. this is a revision shortly after release-pypy-6.0.0 .. startrev: e50e11af23f1 +.. branch: cppyy-packaging +Upgrade to backend 0.6.0, support exception handling from wrapped functions, +update enum handling, const correctness for data members and associated tests, +support anonymous enums, support for function pointer arguments +.. branch: socket_default_timeout_blockingness + +Make sure 'blocking-ness' of socket is set along with default timeout + +.. branch: crypt_h + +Include crypt.h for crypt() on Linux diff --git a/pypy/module/_cppyy/__init__.py b/pypy/module/_cppyy/__init__.py --- a/pypy/module/_cppyy/__init__.py +++ b/pypy/module/_cppyy/__init__.py @@ -7,6 +7,7 @@ interpleveldefs = { '_resolve_name' : 'interp_cppyy.resolve_name', '_scope_byname' : 'interp_cppyy.scope_byname', + '_is_static_data' : 'interp_cppyy.is_static_data', '_is_template' : 'interp_cppyy.is_template', '_std_string_name' : 'interp_cppyy.std_string_name', '_set_class_generator' : 'interp_cppyy.set_class_generator', @@ -21,7 +22,7 @@ } appleveldefs = { - '_init_pythonify' : 'pythonify._init_pythonify', + '_post_import_startup' : 'pythonify._post_import_startup', 'add_pythonization' : 'pythonify.add_pythonization', 'Template' : 'pythonify.CPPTemplate', } @@ -34,9 +35,3 @@ # code generation is not, so give it a chance to run now from pypy.module._cppyy import capi capi.register_pythonizations(space) - - def startup(self, space): - from pypy.module._cppyy import capi - capi.verify_backend(space) # may raise ImportError - - space.call_method(self, '_init_pythonify') 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 @@ -308,7 +308,7 @@ c_call = state.capi_calls[name] except KeyError: if state.backend is None: - load_backend(space) + verify_backend(space) iface = state.capi_call_ifaces[name] cfunc = W_RCTypeFunc(space, iface[0], iface[1], False) c_call = state.backend.load_function(cfunc, 'cppyy_'+name) @@ -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,34 @@ decref(space, rffi.cast(PyObject, rffi.cast(rffi.VOIDPP, arg)[0])) +class FunctionPointerConverter(TypeConverter): + _immutable_fields_ = ['signature'] + + 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 ... @@ -749,6 +777,14 @@ return InstancePtrPtrConverter(space, clsdecl) elif compound == "": return InstanceConverter(space, clsdecl) + 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 + pos = name.find("*)") + if pos > 0: + return FunctionPointerConverter(space, name[pos+2:]) # 5) void* or void converter (which fails on use) if 0 <= compound.find('*'): diff --git a/pypy/module/_cppyy/executor.py b/pypy/module/_cppyy/executor.py --- a/pypy/module/_cppyy/executor.py +++ b/pypy/module/_cppyy/executor.py @@ -293,6 +293,9 @@ return InstancePtrExecutor(space, cppclass) elif compound == '**' or compound == '*&': return InstancePtrPtrExecutor(space, cppclass) + elif "(anonymous)" in name: + # special case: enum w/o a type name + return _executors["internal_enum_type_t"](space, None) # 4) additional special cases if compound == '*': 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) @@ -149,6 +149,24 @@ W_CPPLibrary.typedef.acceptable_as_base_class = True +#----- +# Classes involved with methods and functions: +# +# CPPMethod: base class wrapping a single function or method +# CPPConstructor: specialization for allocating a new object +# CPPFunction: specialization for free and static functions +# CPPSetItem: specialization for Python's __setitem__ +# CPPTemplatedCall: trampoline to instantiate and bind templated functions +# W_CPPOverload, W_CPPConstructorOverload, W_CPPTemplateOverload: +# user-facing, app-level, collection of overloads, with specializations +# for constructors and templates +# W_CPPBoundMethod: instantiated template method +# +# All methods/functions derive from CPPMethod and are collected as overload +# candidates in user-facing overload classes. Templated methods are a two-step +# process, where first the template is instantiated (or selected if already +# available), which returns a callable object that is the actual bound method. + class CPPMethod(object): """Dispatcher of methods. Checks the arguments, find the corresponding FFI function if available, makes the call, and returns the wrapped result. It @@ -177,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) @@ -424,7 +442,7 @@ class CPPFunction(CPPMethod): - """Global (namespaced) function dispatcher.""" + """Global (namespaced) / static function dispatcher.""" _immutable_ = True @@ -688,6 +706,18 @@ ) +#----- +# Classes for data members: +# +# W_CPPDataMember: instance data members +# W_CPPConstDataMember: specialization for const data members +# W_CPPStaticData: class-level and global/static data +# W_CPPConstStaticData: specialization for const global/static data +# +# Data is represented by an offset which is either a global pointer (static data) +# or an offset from the start of an instance (data members). The "const" +# specializations raise when attempting to set their value. + class W_CPPDataMember(W_Root): _attrs_ = ['space', 'scope', 'converter', 'offset'] _immutable_fields = ['scope', 'converter', 'offset'] @@ -698,9 +728,6 @@ self.converter = converter.get_converter(self.space, type_name, '') self.offset = offset - def is_static(self): - return self.space.w_False - def _get_offset(self, cppinstance): if cppinstance: assert lltype.typeOf(cppinstance.clsdecl.handle) == lltype.typeOf(self.scope.handle) @@ -728,16 +755,25 @@ W_CPPDataMember.typedef = TypeDef( 'CPPDataMember', - is_static = interp2app(W_CPPDataMember.is_static), __get__ = interp2app(W_CPPDataMember.get), __set__ = interp2app(W_CPPDataMember.set), ) W_CPPDataMember.typedef.acceptable_as_base_class = False + +class W_CPPConstDataMember(W_CPPDataMember): + def set(self, w_cppinstance, w_value): + raise oefmt(self.space.w_TypeError, "assignment to const data not allowed") + +W_CPPConstDataMember.typedef = TypeDef( + 'CPPConstDataMember', + __get__ = interp2app(W_CPPDataMember.get), + __set__ = interp2app(W_CPPConstDataMember.set), +) +W_CPPConstDataMember.typedef.acceptable_as_base_class = False + + class W_CPPStaticData(W_CPPDataMember): - def is_static(self): - return self.space.w_True - @jit.elidable_promote() def _get_offset(self, cppinstance): return self.offset @@ -751,19 +787,34 @@ W_CPPStaticData.typedef = TypeDef( 'CPPStaticData', - is_static = interp2app(W_CPPStaticData.is_static), __get__ = interp2app(W_CPPStaticData.get), __set__ = interp2app(W_CPPStaticData.set), ) W_CPPStaticData.typedef.acceptable_as_base_class = False -def is_static(space, w_obj): + +class W_CPPConstStaticData(W_CPPStaticData): + def set(self, w_cppinstance, w_value): + raise oefmt(self.space.w_TypeError, "assignment to const data not allowed") + +W_CPPConstStaticData.typedef = TypeDef( + 'CPPConstStaticData', + __get__ = interp2app(W_CPPConstStaticData.get), + __set__ = interp2app(W_CPPConstStaticData.set), +) +W_CPPConstStaticData.typedef.acceptable_as_base_class = False + + +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 +#----- + + class W_CPPScopeDecl(W_Root): _attrs_ = ['space', 'handle', 'name', 'methods', 'datamembers'] _immutable_fields_ = ['handle', 'name'] @@ -847,7 +898,10 @@ offset = capi.c_datamember_offset(self.space, self, dm_idx) if offset == -1: raise self.missing_attribute_error(dm_name) - datamember = W_CPPStaticData(self.space, self, type_name, offset) + if capi.c_is_const_data(self.space, self, dm_idx): + datamember = W_CPPConstStaticData(self.space, self, type_name, offset) + else: + datamember = W_CPPStaticData(self.space, self, type_name, offset) self.datamembers[dm_name] = datamember return datamember @@ -967,8 +1021,13 @@ if offset == -1: continue # dictionary problem; raises AttributeError on use is_static = bool(capi.c_is_staticdata(self.space, self, i)) - if is_static: + is_const = bool(capi.c_is_const_data(self.space, self, i)) + if is_static and is_const: + datamember = W_CPPConstStaticData(self.space, self, type_name, offset) + elif is_static: datamember = W_CPPStaticData(self.space, self, type_name, offset) + elif is_const: + datamember = W_CPPConstDataMember(self.space, self, type_name, offset) else: datamember = W_CPPDataMember(self.space, self, type_name, offset) self.datamembers[datamember_name] = datamember @@ -1124,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( @@ -1146,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) @@ -1265,7 +1324,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 @@ -1283,7 +1342,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 @@ -1311,7 +1370,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) @@ -1327,7 +1386,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/pythonify.py b/pypy/module/_cppyy/pythonify.py --- a/pypy/module/_cppyy/pythonify.py +++ b/pypy/module/_cppyy/pythonify.py @@ -1,5 +1,5 @@ # NOT_RPYTHON -# do not load _cppyy here, see _init_pythonify() +# do not load _cppyy here, see _post_import_startup() import types import sys @@ -22,7 +22,7 @@ class CPPClass(CPPScope): pass -# namespace base class (class base class defined in _init_pythonify) +# namespace base class (class base class defined in _post_import_startup() class CPPNamespace(object): __metatype__ = CPPMetaNamespace @@ -169,6 +169,7 @@ return method def make_cppclass(scope, cl_name, decl): + import _cppyy # get a list of base classes for class creation bases = [get_pycppclass(base) for base in decl.get_base_names()] @@ -209,7 +210,7 @@ for d_name in decl.get_datamember_names(): cppdm = decl.get_datamember(d_name) d_class[d_name] = cppdm - if cppdm.is_static(): + if _cppyy._is_static_data(cppdm): d_meta[d_name] = cppdm # create a metaclass to allow properties (for static data write access) @@ -278,7 +279,7 @@ try: cppdm = scope.__cppdecl__.get_datamember(name) setattr(scope, name, cppdm) - if cppdm.is_static(): + if _cppyy._is_static_data(cppdm): setattr(scope.__class__, name, cppdm) pycppitem = getattr(scope, name) # gets actual property value except AttributeError: @@ -406,7 +407,7 @@ pyclass.__len__ = return2 -def _init_pythonify(): +def _post_import_startup(): # _cppyy should not be loaded at the module level, as that will trigger a # call to space.getbuiltinmodule(), which will cause _cppyy to be loaded # at pypy-c startup, rather than on the "import _cppyy" statement diff --git a/pypy/module/_cppyy/src/dummy_backend.cxx b/pypy/module/_cppyy/src/dummy_backend.cxx --- a/pypy/module/_cppyy/src/dummy_backend.cxx +++ b/pypy/module/_cppyy/src/dummy_backend.cxx @@ -348,6 +348,7 @@ PUBLIC_CPPYY_DATA3(short, short, h); PUBLIC_CPPYY_DATA3(ushort, unsigned short, H); PUBLIC_CPPYY_DATA3(int, int, i); + PUBLIC_CPPYY_DATA (const_int, const int); PUBLIC_CPPYY_DATA3(uint, unsigned int, I); PUBLIC_CPPYY_DATA3(long, long, l); PUBLIC_CPPYY_DATA3(ulong, unsigned long, L); @@ -1032,7 +1033,9 @@ return s_scopes[handle].m_datambrs[idatambr].m_isstatic; } -int cppyy_is_const_data(cppyy_scope_t /* handle */, cppyy_index_t /* idatambr */) { +int cppyy_is_const_data(cppyy_scope_t handle, cppyy_index_t idatambr) { + if (s_scopes[handle].m_datambrs[idatambr].m_name == "m_const_int") + return 1; return 0; } diff --git a/pypy/module/_cppyy/test/datatypes.cxx b/pypy/module/_cppyy/test/datatypes.cxx --- a/pypy/module/_cppyy/test/datatypes.cxx +++ b/pypy/module/_cppyy/test/datatypes.cxx @@ -6,7 +6,7 @@ //=========================================================================== -CppyyTestData::CppyyTestData() : m_owns_arrays(false) +CppyyTestData::CppyyTestData() : m_const_int(17), m_owns_arrays(false) { m_bool = false; m_char = 'a'; @@ -333,3 +333,17 @@ CppyyTestPod* get_null_pod() { return (CppyyTestPod*)0; } + + +//= function pointer passing ================================================ +int sum_of_int(int i1, int i2) { + return i1+i2; +} + +double sum_of_double(double d1, double d2) { + return d1+d2; +} + +double call_double_double(double (*d)(double, double), double d1, double d2) { + return d(d1, d2); +} diff --git a/pypy/module/_cppyy/test/datatypes.h b/pypy/module/_cppyy/test/datatypes.h --- a/pypy/module/_cppyy/test/datatypes.h +++ b/pypy/module/_cppyy/test/datatypes.h @@ -1,5 +1,5 @@ // copied from RtypesCore.h ... -#if defined(R__WIN32) +#if defined(R__WIN32) && !defined(__CINT__) typedef __int64 Long64_t; //Portable signed long integer 8 bytes typedef unsigned __int64 ULong64_t; //Portable unsigned long integer 8 bytes #else @@ -26,8 +26,13 @@ //=========================================================================== namespace EnumSpace { - enum E {E1 = 1, E2}; -}; + enum E {E1 = 1, E2}; + class EnumClass { + public: + enum {E1 = -1}; + enum EE {E2 = -1}; + }; +} //=========================================================================== @@ -243,6 +248,7 @@ short m_short; unsigned short m_ushort; int m_int; + const int m_const_int; // special case: const testing unsigned int m_uint; long m_long; unsigned long m_ulong; @@ -364,3 +370,9 @@ void set_global_pod(CppyyTestPod* t); CppyyTestPod* get_global_pod(); CppyyTestPod* get_null_pod(); + + +//= function pointer passing ================================================ +int sum_of_int(int i1, int i2); +double sum_of_double(double d1, double d2); +double call_double_double(double (*d)(double, double), double d1, double d2); diff --git a/pypy/module/_cppyy/test/datatypes.xml b/pypy/module/_cppyy/test/datatypes.xml --- a/pypy/module/_cppyy/test/datatypes.xml +++ b/pypy/module/_cppyy/test/datatypes.xml @@ -4,6 +4,8 @@ <class name="FourVector" /> <enum name="EFruit" /> + <enum name="EnumSpace::E" /> + <class name="EnumSpace::EnumClass" /> <function pattern="get_*" /> <function pattern="set_*" /> @@ -14,4 +16,8 @@ <variable name="g_int" /> <variable name="g_pod" /> + <function name="sum_of_int" /> + <function name="sum_of_double" /> + <function name="call_double_double" /> + </lcgdict> diff --git a/pypy/module/_cppyy/test/test_advancedcpp.py b/pypy/module/_cppyy/test/test_advancedcpp.py --- a/pypy/module/_cppyy/test/test_advancedcpp.py +++ b/pypy/module/_cppyy/test/test_advancedcpp.py @@ -22,7 +22,8 @@ def setup_class(cls): cls.w_test_dct = cls.space.newtext(test_dct) cls.w_advanced = cls.space.appexec([], """(): - import ctypes + import ctypes, _cppyy + _cppyy._post_import_startup() return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, )) def test01_default_arguments(self): diff --git a/pypy/module/_cppyy/test/test_cpp11features.py b/pypy/module/_cppyy/test/test_cpp11features.py --- a/pypy/module/_cppyy/test/test_cpp11features.py +++ b/pypy/module/_cppyy/test/test_cpp11features.py @@ -14,7 +14,8 @@ def setup_class(cls): cls.w_test_dct = cls.space.newtext(test_dct) cls.w_example01 = cls.space.appexec([], """(): - import ctypes + import ctypes, _cppyy + _cppyy._post_import_startup() return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, )) def test01_shared_ptr(self): diff --git a/pypy/module/_cppyy/test/test_cppyy.py b/pypy/module/_cppyy/test/test_cppyy.py --- a/pypy/module/_cppyy/test/test_cppyy.py +++ b/pypy/module/_cppyy/test/test_cppyy.py @@ -33,6 +33,7 @@ cls.w_lib, cls.w_instantiate, cls.w_example01, cls.w_payload = \ cls.space.unpackiterable(cls.space.appexec([], """(): import _cppyy, ctypes + _cppyy._post_import_startup() lib = ctypes.CDLL(%r, ctypes.RTLD_GLOBAL) def cpp_instantiate(tt, *args): inst = _cppyy._bind_object(0, tt, True) diff --git a/pypy/module/_cppyy/test/test_crossing.py b/pypy/module/_cppyy/test/test_crossing.py --- a/pypy/module/_cppyy/test/test_crossing.py +++ b/pypy/module/_cppyy/test/test_crossing.py @@ -72,7 +72,9 @@ # to allow the generated extension module be loaded first) cls.w_test_dct = cls.space.newtext(test_dct) cls.w_pre_imports = cls.space.appexec([], """(): - import ctypes, _cppyy""") # prevents leak-checking complaints on ctypes' statics + import ctypes, _cppyy + _cppyy._post_import_startup()""") # early import of ctypes + # prevents leak-checking complaints on ctypes' statics def setup_method(self, func): @unwrap_spec(name='text', init='text', body='text') 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 @@ -14,7 +14,8 @@ def setup_class(cls): cls.w_test_dct = cls.space.newtext(test_dct) cls.w_datatypes = cls.space.appexec([], """(): - import ctypes + import ctypes, _cppyy + _cppyy._post_import_startup() return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, )) cls.w_N = cls.space.newint(5) # should be imported from the dictionary @@ -193,6 +194,10 @@ for i in range(self.N): assert eval('c.m_%s_array2[i]' % names[j]) == b[i] + # can not write to constant data + assert c.m_const_int == 17 + raises(TypeError, setattr, c, 'm_const_int', 71) + c.__destruct__() def test03_array_passing(self): @@ -466,6 +471,10 @@ assert gbl.kBanana == 29 assert gbl.kCitrus == 34 + assert gbl.EnumSpace.E + assert gbl.EnumSpace.EnumClass.E1 == -1 # anonymous + assert gbl.EnumSpace.EnumClass.E2 == -1 # named type + def test11_string_passing(self): """Test passing/returning of a const char*""" @@ -743,3 +752,22 @@ c.s_voidp = c2 address_equality_test(c.s_voidp, c2) + + def test21_function_pointers(self): + """Function pointer passing""" + + import _cppyy as cppyy + + f1 = cppyy.gbl.sum_of_int + f2 = cppyy.gbl.sum_of_double + f3 = cppyy.gbl.call_double_double + + assert 5 == f1(2, 3) + assert 5. == f2(5., 0.) + + 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.) diff --git a/pypy/module/_cppyy/test/test_fragile.py b/pypy/module/_cppyy/test/test_fragile.py --- a/pypy/module/_cppyy/test/test_fragile.py +++ b/pypy/module/_cppyy/test/test_fragile.py @@ -14,7 +14,8 @@ def setup_class(cls): cls.w_test_dct = cls.space.newtext(test_dct) cls.w_fragile = cls.space.appexec([], """(): - import ctypes + import ctypes, _cppyy + _cppyy._post_import_startup() return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, )) def test01_missing_classes(self): diff --git a/pypy/module/_cppyy/test/test_operators.py b/pypy/module/_cppyy/test/test_operators.py --- a/pypy/module/_cppyy/test/test_operators.py +++ b/pypy/module/_cppyy/test/test_operators.py @@ -15,7 +15,8 @@ cls.w_N = cls.space.newint(5) # should be imported from the dictionary cls.w_test_dct = cls.space.newtext(test_dct) cls.w_operators = cls.space.appexec([], """(): - import ctypes + import ctypes, _cppyy + _cppyy._post_import_startup() return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, )) def teardown_method(self, meth): diff --git a/pypy/module/_cppyy/test/test_overloads.py b/pypy/module/_cppyy/test/test_overloads.py --- a/pypy/module/_cppyy/test/test_overloads.py +++ b/pypy/module/_cppyy/test/test_overloads.py @@ -17,7 +17,8 @@ def setup_class(cls): cls.w_test_dct = cls.space.newtext(test_dct) cls.w_overloads = cls.space.appexec([], """(): - import ctypes + import ctypes, _cppyy + _cppyy._post_import_startup() return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, )) def test01_class_based_overloads(self): diff --git a/pypy/module/_cppyy/test/test_pythonify.py b/pypy/module/_cppyy/test/test_pythonify.py --- a/pypy/module/_cppyy/test/test_pythonify.py +++ b/pypy/module/_cppyy/test/test_pythonify.py @@ -16,7 +16,8 @@ def setup_class(cls): cls.w_test_dct = cls.space.newtext(test_dct) cls.w_example01 = cls.space.appexec([], """(): - import ctypes + import ctypes, _cppyy + _cppyy._post_import_startup() return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, )) def test01_finding_classes(self): diff --git a/pypy/module/_cppyy/test/test_stltypes.py b/pypy/module/_cppyy/test/test_stltypes.py --- a/pypy/module/_cppyy/test/test_stltypes.py +++ b/pypy/module/_cppyy/test/test_stltypes.py @@ -15,7 +15,8 @@ cls.w_N = cls.space.newint(13) cls.w_test_dct = cls.space.newtext(test_dct) cls.w_stlvector = cls.space.appexec([], """(): - import ctypes + import ctypes, _cppyy + _cppyy._post_import_startup() return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, )) def test01_builtin_type_vector_types(self): diff --git a/pypy/module/_cppyy/test/test_templates.py b/pypy/module/_cppyy/test/test_templates.py --- a/pypy/module/_cppyy/test/test_templates.py +++ b/pypy/module/_cppyy/test/test_templates.py @@ -14,7 +14,8 @@ def setup_class(cls): cls.w_test_dct = cls.space.newtext(test_dct) cls.w_datatypes = cls.space.appexec([], """(): - import ctypes + import ctypes, _cppyy + _cppyy._post_import_startup() return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, )) def test01_template_member_functions(self): diff --git a/pypy/module/cpyext/include/pyport.h b/pypy/module/cpyext/include/pyport.h --- a/pypy/module/cpyext/include/pyport.h +++ b/pypy/module/cpyext/include/pyport.h @@ -128,4 +128,36 @@ #else #endif +/* + * Hide GCC attributes from compilers that don't support them. + */ +#if (!defined(__GNUC__) || __GNUC__ < 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ) && \ + !defined(RISCOS) +#define Py_GCC_ATTRIBUTE(x) +#else +#define Py_GCC_ATTRIBUTE(x) __attribute__(x) +#endif + +/* + * Specify alignment on compilers that support it. + */ +#if defined(__GNUC__) && __GNUC__ >= 3 +#define Py_ALIGNED(x) __attribute__((aligned(x))) +#else +#define Py_ALIGNED(x) +#endif + +/* + * Older Microsoft compilers don't support the C99 long long literal suffixes, + * so these will be defined in PC/pyconfig.h for those compilers. + */ +#ifndef Py_LL +#define Py_LL(x) x##LL +#endif + +#ifndef Py_ULL +#define Py_ULL(x) Py_LL(x##U) +#endif + #endif /* Py_PYPORT_H */ diff --git a/pypy/module/crypt/interp_crypt.py b/pypy/module/crypt/interp_crypt.py --- a/pypy/module/crypt/interp_crypt.py +++ b/pypy/module/crypt/interp_crypt.py @@ -5,6 +5,9 @@ if sys.platform.startswith('darwin'): eci = ExternalCompilationInfo() +elif sys.platform.startswith('linux'): + # crypt() is defined only in crypt.h on some Linux variants (eg. Fedora 28) + eci = ExternalCompilationInfo(libraries=['crypt'], includes=["crypt.h"]) else: eci = ExternalCompilationInfo(libraries=['crypt']) c_crypt = rffi.llexternal('crypt', [rffi.CCHARP, rffi.CCHARP], rffi.CCHARP, diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py --- a/pypy/objspace/std/floatobject.py +++ b/pypy/objspace/std/floatobject.py @@ -410,7 +410,6 @@ def descr_hash(self, space): h = _hash_float(space, self.floatval) - h -= (h == -1) return space.newint(h) def descr_format(self, space, w_spec): @@ -761,7 +760,8 @@ x = ((x << e) & HASH_MODULUS) | x >> (HASH_BITS - e) x = intmask(intmask(x) * sign) - return -2 if x == -1 else x + x -= (x == -1) + return x def _divmod_w(space, w_float1, w_float2): diff --git a/rpython/rlib/rvmprof/src/shared/vmp_stack.c b/rpython/rlib/rvmprof/src/shared/vmp_stack.c --- a/rpython/rlib/rvmprof/src/shared/vmp_stack.c +++ b/rpython/rlib/rvmprof/src/shared/vmp_stack.c @@ -214,7 +214,7 @@ ret = unw_getcontext(&uc); if (ret < 0) { // could not initialize lib unwind cursor and context - fprintf(stderr, "WARNING: unw_getcontext did not retrieve context, switching to python profiling mode \n"); + fprintf(stderr, "WARNING: unw_getcontext did not retreive context, switching to python profiling mode \n"); vmp_native_disable(); return vmp_walk_and_record_python_stack_only(frame, result, max_depth, 0, pc); } _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit