Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit