Author: Wim Lavrijsen <[email protected]>
Branch:
Changeset: r94499:a4c2916c877f
Date: 2018-05-07 21:02 -0700
http://bitbucket.org/pypy/pypy/changeset/a4c2916c877f/
Log: Merge of cppyy-packaging: pulls in fully deferred loading for the
backend (needed for pydoc tests in p3.5 branch), support for
function pointer arguments, proper types for anonymous enums, and
correct handling of const data.
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
@@ -289,6 +289,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
@@ -191,6 +192,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):
@@ -464,6 +469,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*"""
@@ -741,3 +750,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):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit