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

Reply via email to