aboutsummaryrefslogtreecommitdiff
path: root/pypy
diff options
context:
space:
mode:
authorWim Lavrijsen <WLavrijsen@lbl.gov>2021-02-09 22:07:04 -0800
committerWim Lavrijsen <WLavrijsen@lbl.gov>2021-02-09 22:07:04 -0800
commit3d208ca56d8606d9d18a347d75b654cc9bbfc635 (patch)
treec236eae1c802ee5e56918ec6bf7fb56ef3708654 /pypy
parentbackport changes to _ctypes needed for maxos BigSur from py3.7 (diff)
parentmerge default into cppyy_packaging branch (diff)
downloadpypy-3d208ca56d8606d9d18a347d75b654cc9bbfc635.tar.gz
pypy-3d208ca56d8606d9d18a347d75b654cc9bbfc635.tar.bz2
pypy-3d208ca56d8606d9d18a347d75b654cc9bbfc635.zip
updated API to cppyy_backend 1.14.2, consistent types for Win64, support for new builtin types
Diffstat (limited to 'pypy')
-rw-r--r--pypy/doc/whatsnew-head.rst6
-rw-r--r--pypy/module/_cppyy/capi/capi_types.py29
-rw-r--r--pypy/module/_cppyy/capi/loadable_capi.py378
-rw-r--r--pypy/module/_cppyy/converter.py243
-rw-r--r--pypy/module/_cppyy/executor.py186
-rw-r--r--pypy/module/_cppyy/ffitypes.py160
-rw-r--r--pypy/module/_cppyy/helper.py2
-rw-r--r--pypy/module/_cppyy/include/capi.h41
-rw-r--r--pypy/module/_cppyy/interp_cppyy.py156
-rw-r--r--pypy/module/_cppyy/pythonify.py59
-rw-r--r--pypy/module/_cppyy/src/dummy_backend.cxx487
-rw-r--r--pypy/module/_cppyy/test/Makefile11
-rw-r--r--pypy/module/_cppyy/test/datatypes.cxx800
-rw-r--r--pypy/module/_cppyy/test/datatypes.h407
-rw-r--r--pypy/module/_cppyy/test/datatypes.xml45
-rwxr-xr-xpypy/module/_cppyy/test/make_dict_win32.py108
-rw-r--r--pypy/module/_cppyy/test/support.py28
-rw-r--r--pypy/module/_cppyy/test/templates.cxx19
-rw-r--r--pypy/module/_cppyy/test/templates.h55
-rw-r--r--pypy/module/_cppyy/test/templates.xml7
-rw-r--r--pypy/module/_cppyy/test/test_advancedcpp.py6
-rw-r--r--pypy/module/_cppyy/test/test_boost.py185
-rw-r--r--pypy/module/_cppyy/test/test_cpp11features.py8
-rw-r--r--pypy/module/_cppyy/test/test_cppyy.py9
-rw-r--r--pypy/module/_cppyy/test/test_crossing.py8
-rw-r--r--pypy/module/_cppyy/test/test_datatypes.py234
-rw-r--r--pypy/module/_cppyy/test/test_fragile.py122
-rw-r--r--pypy/module/_cppyy/test/test_operators.py84
-rw-r--r--pypy/module/_cppyy/test/test_pythonify.py8
-rw-r--r--pypy/module/_cppyy/test/test_pythonization.py12
-rw-r--r--pypy/module/_cppyy/test/test_regression.py2
-rw-r--r--pypy/module/_cppyy/test/test_stltypes.py8
-rw-r--r--pypy/module/_cppyy/test/test_templates.py742
-rw-r--r--pypy/module/_cppyy/test/test_zjit.py35
34 files changed, 3583 insertions, 1107 deletions
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
index 3e2410d9b7..7a4e4c67bb 100644
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -74,3 +74,9 @@ Update the version of Tk/Tcl on windows to 8.6
.. branch: big-sur-dyld-cache
Backport changes to ``_ctypes`` needed for maxos BigSur from py3.7
+
+.. branch: cppyy-packaging
+
+Updated the API to the latest cppyy_backend (1.14.2), made all types used
+consistent to avoid void*/long casting problems on Win64, and added several
+new "builtin" types (wide chars, complex, etc.).
diff --git a/pypy/module/_cppyy/capi/capi_types.py b/pypy/module/_cppyy/capi/capi_types.py
index 0d0f6fb8e8..4b744111b9 100644
--- a/pypy/module/_cppyy/capi/capi_types.py
+++ b/pypy/module/_cppyy/capi/capi_types.py
@@ -1,21 +1,18 @@
from rpython.rtyper.lltypesystem import rffi, lltype
# shared ll definitions
-_C_OPAQUE_PTR = rffi.ULONG
-_C_OPAQUE_NULL = lltype.nullptr(rffi.ULONGP.TO)# ALT: _C_OPAQUE_PTR.TO
+C_SCOPE = rffi.SIZE_T
+C_NULL_SCOPE = rffi.cast(C_SCOPE, 0)
+C_TYPE = C_SCOPE
+C_NULL_TYPE = rffi.cast(C_TYPE, 0)
+C_ENUM = rffi.VOIDP
+C_NULL_ENUM = rffi.cast(C_ENUM, 0)
+C_OBJECT = rffi.VOIDP
+C_NULL_OBJECT = rffi.cast(C_OBJECT, 0)
+C_METHOD = rffi.INTPTR_T
-C_SCOPE = _C_OPAQUE_PTR
-C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL)
+C_INDEX = rffi.SIZE_T
+C_INDEX_ARRAY = rffi.CArrayPtr(rffi.SIZE_T)
+C_FUNC_PTR = rffi.VOIDP
-C_TYPE = C_SCOPE
-C_NULL_TYPE = C_NULL_SCOPE
-
-C_OBJECT = _C_OPAQUE_PTR
-C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL)
-
-C_METHOD = _C_OPAQUE_PTR
-C_INDEX = rffi.LONG
-C_INDEX_ARRAY = rffi.LONGP
-WLAVC_INDEX = rffi.LONG
-
-C_FUNC_PTR = rffi.VOIDP
+C_EXCTYPE = rffi.ULONG
diff --git a/pypy/module/_cppyy/capi/loadable_capi.py b/pypy/module/_cppyy/capi/loadable_capi.py
index f358ac4693..b371c8ce47 100644
--- a/pypy/module/_cppyy/capi/loadable_capi.py
+++ b/pypy/module/_cppyy/capi/loadable_capi.py
@@ -13,12 +13,13 @@ from pypy.interpreter.typedef import TypeDef
from pypy.objspace.std.iterobject import W_AbstractSeqIterObject
from pypy.module._rawffi.interp_array import W_ArrayInstance
-from pypy.module._cffi_backend import ctypefunc, ctypeprim, cdataobj, misc
+from pypy.module._cffi_backend import ctypefunc, cdataobj, misc
from pypy.module._cffi_backend import newtype
from pypy.module._cppyy import ffitypes
+from pypy.module.sys.version import PYPY_VERSION
from pypy.module._cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\
- C_METHOD, C_INDEX, C_INDEX_ARRAY, WLAVC_INDEX, C_FUNC_PTR
+ C_METHOD, C_INDEX, C_INDEX_ARRAY, C_FUNC_PTR
backend_ext = '.so'
if sys.platform == 'win32':
@@ -34,29 +35,52 @@ std_string_name = 'std::string'
class _Arg: # poor man's union
_immutable_ = True
- def __init__(self, tc, h = 0, u = 0, l = -1, d = -1., s = '', p = rffi.cast(rffi.VOIDP, 0)):
+ def __init__(self, tc, h = rffi.cast(C_SCOPE, 0),
+ m = rffi.cast(C_METHOD, 0),
+ o = rffi.cast(C_OBJECT, 0),
+ u = rffi.cast(C_INDEX, -1),
+ i = rffi.cast(rffi.INT, -1),
+ d = rffi.cast(rffi.DOUBLE, -1.),
+ s = '',
+ p = rffi.cast(rffi.VOIDP, 0)):
self.tc = tc
- self._handle = h
+ self._scope = h
+ self._method = m
+ self._object = o
self._index = u
- self._long = l
+ self._int = i
self._double = d
self._string = s
self._voidp = p
+# use separate classes for the benefit of the rtyper
class _ArgH(_Arg):
_immutable_ = True
def __init__(self, val):
_Arg.__init__(self, 'h', h = val)
-class _ArgU(_Arg): # separate class for rtyper
+def _ArgC(val):
+ return _ArgH(val.handle)
+
+class _ArgM(_Arg):
+ _immutable_ = True
+ def __init__(self, val):
+ _Arg.__init__(self, 'm', m = val)
+
+class _ArgO(_Arg):
+ _immutable_ = True
+ def __init__(self, val):
+ _Arg.__init__(self, 'o', o = val)
+
+class _ArgU(_Arg):
_immutable_ = True
def __init__(self, val):
_Arg.__init__(self, 'u', u = val)
-class _ArgL(_Arg):
+class _ArgI(_Arg):
_immutable_ = True
def __init__(self, val):
- _Arg.__init__(self, 'l', l = val)
+ _Arg.__init__(self, 'i', i = val)
class _ArgD(_Arg):
_immutable_ = True
@@ -102,24 +126,23 @@ class W_RCTypeFunc(ctypefunc.W_CTypeFunc):
argtype = self.fargs[i]
# the following is clumsy, but the data types used as arguments are
# very limited, so it'll do for now
- if obj.tc == 'l':
- assert isinstance(argtype, ctypeprim.W_CTypePrimitiveSigned)
- misc.write_raw_signed_data(data, rffi.cast(rffi.LONG, obj._long), argtype.size)
- elif obj.tc == 'h':
- assert isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned)
- misc.write_raw_unsigned_data(data, rffi.cast(rffi.UINTPTR_T, obj._handle), argtype.size)
+ if obj.tc == 'h':
+ misc.write_raw_unsigned_data(data, rffi.cast(rffi.SIZE_T, obj._scope), argtype.size)
+ elif obj.tc == 'm':
+ misc.write_raw_signed_data(data, rffi.cast(rffi.INTPTR_T, obj._method), argtype.size)
+ elif obj.tc == 'o':
+ misc.write_raw_signed_data(data, rffi.cast(rffi.VOIDP, obj._object), argtype.size)
elif obj.tc == 'u':
- assert isinstance(argtype, ctypeprim.W_CTypePrimitiveUnsigned)
misc.write_raw_unsigned_data(data, rffi.cast(rffi.SIZE_T, obj._index), argtype.size)
+ elif obj.tc == 'i':
+ misc.write_raw_signed_data(data, rffi.cast(rffi.INT, obj._int), argtype.size)
+ elif obj.tc == 'd':
+ misc.write_raw_float_data(data, rffi.cast(rffi.DOUBLE, obj._double), argtype.size)
elif obj.tc == 'p':
assert obj._voidp != rffi.cast(rffi.VOIDP, 0)
data = rffi.cast(rffi.VOIDPP, data)
data[0] = obj._voidp
- elif obj.tc == 'd':
- assert isinstance(argtype, ctypeprim.W_CTypePrimitiveFloat)
- misc.write_raw_float_data(data, rffi.cast(rffi.DOUBLE, obj._double), argtype.size)
- else: # only other use is string
- assert obj.tc == 's'
+ elif obj.tc == 's':
n = len(obj._string)
data = rffi.cast(rffi.CCHARPP, data)
if raw_string1 == rffi.cast(rffi.CCHARP, 0):
@@ -130,6 +153,11 @@ class W_RCTypeFunc(ctypefunc.W_CTypeFunc):
assert raw_string2 == rffi.cast(rffi.CCHARP, 0)
raw_string2 = rffi.str2charp(obj._string)
data[0] = raw_string2
+ else: # only other use is voidp
+ assert obj.tc == 'p'
+ assert obj._voidp != rffi.cast(rffi.VOIDP, 0)
+ data = rffi.cast(rffi.VOIDPP, data)
+ data[0] = obj._voidp
jit_libffi.jit_ffi_call(cif_descr,
rffi.cast(rffi.VOIDP, funcaddr),
@@ -157,18 +185,18 @@ class State(object):
# TODO: the following need to match up with the globally defined C_XYZ low-level
# types (see capi/__init__.py), but by using strings here, that isn't guaranteed
- c_opaque_ptr = state.c_uintptr_t # not size_t (which is signed)
+ c_voidp = state.c_voidp
c_size_t = state.c_size_t
c_ptrdiff_t = state.c_ptrdiff_t
c_intptr_t = state.c_intptr_t
- c_uintptr_t = state.c_uintptr_t
- c_scope = c_opaque_ptr
+ c_scope = c_size_t
c_type = c_scope
- c_object = c_opaque_ptr # not voidp (to stick with one handle type)
- c_method = c_uintptr_t # not intptr_t (which is signed)
+ c_enum = c_voidp
+ c_object = c_voidp
+ c_method = c_intptr_t
c_index = c_size_t
- c_index_array = state.c_voidp
+ c_index_array = c_voidp
c_void = state.c_void
c_char = state.c_char
@@ -182,12 +210,12 @@ class State(object):
c_double = state.c_double
c_ldouble = state.c_ldouble
- c_ccharp = state.c_ccharp
- c_voidp = state.c_voidp
+ c_ccharp = state.c_ccharp
self.capi_call_ifaces = {
# direct interpreter access
'compile' : ([c_ccharp], c_int),
+ 'cppyy_to_string' : ([c_type, c_object], c_ccharp),
# name to opaque C++ scope representation
'resolve_name' : ([c_ccharp], c_ccharp),
@@ -197,6 +225,9 @@ class State(object):
'size_of_klass' : ([c_type], c_size_t),
'size_of_type' : ([c_ccharp], c_size_t),
+ 'is_builtin' : ([c_ccharp], c_int),
+ 'is_complete' : ([c_ccharp], c_int),
+
# memory management
'allocate' : ([c_type], c_object),
'deallocate' : ([c_type, c_object], c_void),
@@ -220,8 +251,8 @@ class State(object):
'call_r' : ([c_method, c_object, c_int, c_voidp], c_voidp),
# call_s actually takes an size_t* as last parameter, but this will do
'call_s' : ([c_method, c_object, c_int, c_voidp, c_voidp], c_ccharp),
-
'constructor' : ([c_method, c_object, c_int, c_voidp], c_object),
+ 'destructor' : ([c_type, c_object], c_void),
'call_o' : ([c_method, c_object, c_int, c_voidp, c_type], c_object),
'function_address' : ([c_method], c_voidp), # TODO: verify
@@ -237,6 +268,8 @@ class State(object):
'is_template' : ([c_ccharp], c_int),
'is_abstract' : ([c_type], c_int),
'is_enum' : ([c_ccharp], c_int),
+ 'is_aggregate' : ([c_ccharp], c_int),
+ 'is_default_constructable' : ([c_ccharp], c_int),
'get_all_cpp_names' : ([c_scope, c_voidp], c_voidp), # const char**
@@ -250,11 +283,13 @@ class State(object):
'has_complex_hierarchy' : ([c_type], c_int),
'num_bases' : ([c_type], c_int),
'base_name' : ([c_type, c_int], c_ccharp),
- 'is_smartptr' : ([c_type], c_int),
'is_subtype' : ([c_type, c_type], c_int),
+ 'is_smartptr' : ([c_type], c_int),
'smartptr_info' : ([c_ccharp, c_voidp, c_voidp], c_int),
'add_smartptr_type' : ([c_ccharp], c_void),
+ 'add_type_reducer' : ([c_ccharp, c_ccharp], c_void),
+
'base_offset' : ([c_type, c_type, c_object, c_int], c_ptrdiff_t),
# method/function reflection information
@@ -279,14 +314,16 @@ class State(object):
'get_num_templated_methods': ([c_scope], c_int),
'get_templated_method_name': ([c_scope, c_index], c_ccharp),
+ 'is_templated_constructor' : ([c_scope, c_index], c_int),
'exists_method_template' : ([c_scope, c_ccharp], c_int),
'method_is_template' : ([c_scope, c_index], c_int),
- 'get_method_template' : ([c_scope, c_ccharp, c_ccharp], c_method),
+ 'get_method_template' : ([c_scope, c_ccharp, c_ccharp], c_method),
'get_global_operator' : ([c_scope, c_scope, c_scope, c_ccharp], c_index),
# method properties
'is_public_method' : ([c_method], c_int),
+ 'is_protected_method' : ([c_method], c_int),
'is_constructor' : ([c_method], c_int),
'is_destructor' : ([c_method], c_int),
'is_staticmethod' : ([c_method], c_int),
@@ -300,11 +337,18 @@ class State(object):
# data member properties
'is_publicdata' : ([c_scope, c_int], c_int),
+ 'is_protecteddata' : ([c_scope, c_int], c_int),
'is_staticdata' : ([c_scope, c_int], c_int),
'is_const_data' : ([c_scope, c_int], c_int),
'is_enum_data' : ([c_scope, c_int], c_int),
'get_dimension_size' : ([c_scope, c_int, c_int], c_int),
+ # enum properties
+ 'get_enum' : ([c_scope, c_ccharp], c_enum),
+ 'get_num_enum_data' : ([c_enum], c_index),
+ 'get_enum_data_name' : ([c_enum, c_index], c_ccharp),
+ 'get_enum_data_value' : ([c_enum, c_index], c_llong),
+
# misc helpers
'strtoll' : ([c_ccharp], c_llong),
'strtoull' : ([c_ccharp], c_ullong),
@@ -343,8 +387,10 @@ def load_backend(space):
fullname = backend_library+backend_ext
state.backend = W_Library(space, space.newtext(fullname), dldflags)
except Exception as e:
- # TODO: where to find the value '.pypy-41'? Note that this only matters for testing.
- state.backend = W_Library(space, space.newtext(backend_library+'.pypy-41'+backend_ext), dldflags)
+ soabi = space.config.objspace.soabi
+ if soabi is None:
+ soabi = '.pypy-%d%d' % PYPY_VERSION[:2]
+ state.backend = W_Library(space, space.newtext(backend_library+soabi+backend_ext), dldflags)
if state.backend:
# fix constants
@@ -359,7 +405,7 @@ def verify_backend(space):
except Exception:
if objectmodel.we_are_translated():
raise oefmt(space.w_ImportError,
- "missing reflection library %s", backend_library)
+ "missing backend library %s", backend_library)
return False
return True
@@ -380,8 +426,17 @@ def call_capi(space, name, args):
with c_call as ptr:
return c_call.ctype.rcall(ptr, args)
+def _cdata_to_ptr(space, w_cdata):
+ w_cdata = space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False)
+ with w_cdata as ptr:
+ return rffi.cast(rffi.VOIDP, ptr) # escapes (is okay)
+ return rffi.cast(rffi.VOIDP, 0)
+
def _cdata_to_cobject(space, w_cdata):
- return rffi.cast(C_OBJECT, space.uint_w(w_cdata))
+ ptr = _cdata_to_ptr(space, w_cdata)
+ return rffi.cast(C_OBJECT, ptr)
+
+_cdata_to_cenum = _cdata_to_cobject
def _cdata_to_size_t(space, w_cdata):
return rffi.cast(rffi.SIZE_T, space.uint_w(w_cdata))
@@ -392,18 +447,16 @@ def _cdata_to_ptrdiff_t(space, w_cdata):
def _cdata_to_intptr_t(space, w_cdata):
return rffi.cast(rffi.INTPTR_T, space.int_w(w_cdata))
-def _cdata_to_ptr(space, w_cdata): # TODO: this is both a hack and dreadfully slow
- w_cdata = space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False)
- ptr = w_cdata.unsafe_escaping_ptr()
- return rffi.cast(rffi.VOIDP, ptr)
-
def _cdata_to_ccharp(space, w_cdata):
- ptr = _cdata_to_ptr(space, w_cdata) # see above ... something better?
+ ptr = _cdata_to_ptr(space, w_cdata)
return rffi.cast(rffi.CCHARP, ptr)
# direct interpreter access
def c_compile(space, code):
return space.int_w(call_capi(space, 'compile', [_ArgS(code)]))
+def c_cppyy_to_string(space, cppclass, cppobj):
+ args = [_ArgC(cppclass), _ArgO(cppobj)]
+ return charp2str_free(space, call_capi(space, 'cppyy_to_string', args))
# name to opaque C++ scope representation ------------------------------------
def c_resolve_name(space, name):
@@ -413,85 +466,91 @@ def c_resolve_enum(space, name):
def c_get_scope_opaque(space, name):
return rffi.cast(C_SCOPE, space.uint_w(call_capi(space, 'get_scope', [_ArgS(name)])))
def c_actual_class(space, cppclass, cppobj):
- args = [_ArgH(cppclass.handle), _ArgH(cppobj)]
+ args = [_ArgC(cppclass), _ArgO(cppobj)]
return rffi.cast(C_TYPE, space.uint_w(call_capi(space, 'actual_class', args)))
def c_size_of_klass(space, cppclass):
- return _cdata_to_size_t(space, call_capi(space, 'size_of_klass', [_ArgH(cppclass.handle)]))
+ return _cdata_to_size_t(space, call_capi(space, 'size_of_klass', [_ArgC(cppclass)]))
def c_size_of_type(space, name):
return _cdata_to_size_t(space, call_capi(space, 'size_of_type', [_ArgS(name)]))
+def c_is_builtin(space, name):
+ return space.bool_w(call_capi(space, 'is_builtin', [_ArgS(name)]))
+def c_is_complete(space, name):
+ return space.bool_w(call_capi(space, 'is_complete', [_ArgS(name)]))
+
# memory management ----------------------------------------------------------
def c_allocate(space, cppclass):
- return _cdata_to_cobject(space, call_capi(space, 'allocate', [_ArgH(cppclass.handle)]))
-def c_deallocate(space, cppclass, cppobject):
- call_capi(space, 'deallocate', [_ArgH(cppclass.handle), _ArgH(cppobject)])
+ return _cdata_to_cobject(space, call_capi(space, 'allocate', [_ArgC(cppclass)]))
+def c_deallocate(space, cppclass, cppobj):
+ call_capi(space, 'deallocate', [_ArgC(cppclass), _ArgO(cppobj)])
def c_construct(space, cppclass):
- return _cdata_to_cobject(space, call_capi(space, 'construct', [_ArgH(cppclass.handle)]))
-def c_destruct(space, cppclass, cppobject):
- call_capi(space, 'destruct', [_ArgH(cppclass.handle), _ArgH(cppobject)])
+ return _cdata_to_cobject(space, call_capi(space, 'construct', [_ArgC(cppclass)]))
+def c_destruct(space, cppclass, cppobj):
+ call_capi(space, 'destruct', [_ArgC(cppclass), _ArgO(cppobj)])
# method/function dispatching ------------------------------------------------
-def c_call_v(space, cppmethod, cppobject, nargs, cargs):
- args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
+def c_call_v(space, cppmeth, cppobj, nargs, cargs):
+ args = [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs)]
call_capi(space, 'call_v', args)
-def c_call_b(space, cppmethod, cppobject, nargs, cargs):
- args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
+def c_call_b(space, cppmeth, cppobj, nargs, cargs):
+ args = [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs)]
return rffi.cast(rffi.UCHAR, space.c_uint_w(call_capi(space, 'call_b', args)))
-def c_call_c(space, cppmethod, cppobject, nargs, cargs):
- args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
+def c_call_c(space, cppmeth, cppobj, nargs, cargs):
+ args = [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs)]
return rffi.cast(rffi.CHAR, space.text_w(call_capi(space, 'call_c', args))[0])
-def c_call_h(space, cppmethod, cppobject, nargs, cargs):
- args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
+def c_call_h(space, cppmeth, cppobj, nargs, cargs):
+ args = [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs)]
return rffi.cast(rffi.SHORT, space.int_w(call_capi(space, 'call_h', args)))
-def c_call_i(space, cppmethod, cppobject, nargs, cargs):
- args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
+def c_call_i(space, cppmeth, cppobj, nargs, cargs):
+ args = [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs)]
return rffi.cast(rffi.INT, space.c_int_w(call_capi(space, 'call_i', args)))
-def c_call_l(space, cppmethod, cppobject, nargs, cargs):
- args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
+def c_call_l(space, cppmeth, cppobj, nargs, cargs):
+ args = [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs)]
return rffi.cast(rffi.LONG, space.int_w(call_capi(space, 'call_l', args)))
-def c_call_ll(space, cppmethod, cppobject, nargs, cargs):
- args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
+def c_call_ll(space, cppmeth, cppobj, nargs, cargs):
+ args = [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs)]
return rffi.cast(rffi.LONGLONG, space.r_longlong_w(call_capi(space, 'call_ll', args)))
-def c_call_f(space, cppmethod, cppobject, nargs, cargs):
- args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
+def c_call_f(space, cppmeth, cppobj, nargs, cargs):
+ args = [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs)]
return rffi.cast(rffi.FLOAT, r_singlefloat(space.float_w(call_capi(space, 'call_f', args))))
-def c_call_d(space, cppmethod, cppobject, nargs, cargs):
- args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
+def c_call_d(space, cppmeth, cppobj, nargs, cargs):
+ args = [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs)]
return rffi.cast(rffi.DOUBLE, space.float_w(call_capi(space, 'call_d', args)))
-def c_call_ld(space, cppmethod, cppobject, nargs, cargs):
- args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
+def c_call_ld(space, cppmeth, cppobj, nargs, cargs):
+ args = [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs)]
#return rffi.cast(rffi.LONGDOUBLE, space.float_w(call_capi(space, 'call_ld', args)))
# call_nld narrows long double to double
return rffi.cast(rffi.DOUBLE, space.float_w(call_capi(space, 'call_nld', args)))
-def c_call_r(space, cppmethod, cppobject, nargs, cargs):
- args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
+def c_call_r(space, cppmeth, cppobj, nargs, cargs):
+ args = [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs)]
return _cdata_to_ptr(space, call_capi(space, 'call_r', args))
-def c_call_s(space, cppmethod, cppobject, nargs, cargs):
+def c_call_s(space, cppmeth, cppobj, nargs, cargs):
length = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw')
try:
w_cstr = call_capi(space, 'call_s',
- [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs),
+ [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs),
_ArgP(rffi.cast(rffi.VOIDP, length))])
cstr_len = int(intmask(length[0]))
finally:
lltype.free(length, flavor='raw')
return _cdata_to_ccharp(space, w_cstr), cstr_len
-
-def c_constructor(space, cppmethod, cppobject, nargs, cargs):
- args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
+def c_constructor(space, cppmeth, cppobj, nargs, cargs):
+ args = [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs)]
return _cdata_to_cobject(space, call_capi(space, 'constructor', args))
-def c_call_o(space, cppmethod, cppobject, nargs, cargs, cppclass):
- args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs), _ArgH(cppclass.handle)]
+def c_destructor(space, cppclass, cppobj):
+ call_capi(space, 'constructor', [_ArgC(cppclass), _ArgO(cppobj)])
+def c_call_o(space, cppmeth, cppobj, nargs, cargs, cppclass):
+ args = [_ArgM(cppmeth), _ArgO(cppobj), _ArgI(nargs), _ArgP(cargs), _ArgC(cppclass)]
return _cdata_to_cobject(space, call_capi(space, 'call_o', args))
-def c_function_address(space, cppmethod):
+def c_function_address(space, cppmeth):
return rffi.cast(C_FUNC_PTR,
- _cdata_to_ptr(space, call_capi(space, 'function_address', [_ArgH(cppmethod)])))
+ _cdata_to_ptr(space, call_capi(space, 'function_address', [_ArgM(cppmeth)])))
# handling of function argument buffer ---------------------------------------
def c_allocate_function_args(space, size):
- return _cdata_to_ptr(space, call_capi(space, 'allocate_function_args', [_ArgL(size)]))
+ return _cdata_to_ptr(space, call_capi(space, 'allocate_function_args', [_ArgI(size)]))
def c_deallocate_function_args(space, cargs):
call_capi(space, 'deallocate_function_args', [_ArgP(cargs)])
def c_function_arg_sizeof(space):
@@ -507,14 +566,18 @@ def c_is_namespace(space, scope):
def c_is_template(space, name):
return space.bool_w(call_capi(space, 'is_template', [_ArgS(name)]))
def c_is_abstract(space, cpptype):
- return space.bool_w(call_capi(space, 'is_abstract', [_ArgH(cpptype)]))
+ return space.bool_w(call_capi(space, 'is_abstract', [_ArgC(cpptype)]))
def c_is_enum(space, name):
return space.bool_w(call_capi(space, 'is_enum', [_ArgS(name)]))
+def c_is_aggregate(space, name):
+ return space.bool_w(call_capi(space, 'is_aggregate', [_ArgS(name)]))
+def c_is_default_constructable(space, name):
+ return space.bool_w(call_capi(space, 'is_default_constructable', [_ArgS(name)]))
-def c_get_all_cpp_names(space, scope):
+def c_get_all_cpp_names(space, cppscope):
sz = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw', zero=True)
try:
- args = [_ArgH(scope.handle), _ArgP(rffi.cast(rffi.VOIDP, sz))]
+ args = [_ArgC(cppscope), _ArgP(rffi.cast(rffi.VOIDP, sz))]
rawnames = rffi.cast(rffi.CCHARPP,
_cdata_to_ptr(space, call_capi(space, 'get_all_cpp_names', args)))
count = int(intmask(sz[0]))
@@ -530,29 +593,29 @@ def c_get_all_cpp_names(space, scope):
# namespace reflection information
def c_get_using_namespaces(space, cppscope):
- return space.uint_w(call_capi(space, 'get_using_namespaces', [_ArgH(cppscope)]))
+ return space.uint_w(call_capi(space, 'get_using_namespaces', [_ArgC(cppscope)]))
# type/class reflection information ------------------------------------------
-def c_final_name(space, cpptype):
- return charp2str_free(space, call_capi(space, 'final_name', [_ArgH(cpptype)]))
-def c_scoped_final_name(space, cpptype):
- return charp2str_free(space, call_capi(space, 'scoped_final_name', [_ArgH(cpptype)]))
+def c_final_name(space, handle):
+ return charp2str_free(space, call_capi(space, 'final_name', [_ArgH(handle)]))
+def c_scoped_final_name(space, handle):
+ return charp2str_free(space, call_capi(space, 'scoped_final_name', [_ArgH(handle)]))
def c_has_virtual_destructor(space, handle):
return space.bool_w(call_capi(space, 'has_virtual_destructor', [_ArgH(handle)]))
def c_has_complex_hierarchy(space, handle):
return space.bool_w(call_capi(space, 'has_complex_hierarchy', [_ArgH(handle)]))
def c_num_bases(space, cppclass):
- return space.int_w(call_capi(space, 'num_bases', [_ArgH(cppclass.handle)]))
+ return space.int_w(call_capi(space, 'num_bases', [_ArgC(cppclass)]))
def c_base_name(space, cppclass, base_index):
- args = [_ArgH(cppclass.handle), _ArgL(base_index)]
+ args = [_ArgC(cppclass), _ArgI(base_index)]
return charp2str_free(space, call_capi(space, 'base_name', args))
-def c_is_smartptr(space, handle):
- return space.bool_w(call_capi(space, 'is_smartptr', [_ArgH(handle)]))
def c_is_subtype(space, derived, base):
jit.promote(base)
if derived == base:
return bool(1)
- return space.bool_w(call_capi(space, 'is_subtype', [_ArgH(derived.handle), _ArgH(base.handle)]))
+ return space.bool_w(call_capi(space, 'is_subtype', [_ArgC(derived), _ArgC(base)]))
+def c_is_smartptr(space, handle):
+ return space.bool_w(call_capi(space, 'is_smartptr', [_ArgH(handle)]))
def c_smartptr_info(space, name):
out_raw = lltype.malloc(rffi.ULONGP.TO, 1, flavor='raw', zero=True)
out_deref = lltype.malloc(rffi.ULONGP.TO, 1, flavor='raw', zero=True)
@@ -569,8 +632,11 @@ def c_smartptr_info(space, name):
def c_add_smartptr_type(space, name):
return space.bool_w(call_capi(space, 'add_smartptr_type', [_ArgS(name)]))
+def c_add_type_reducer(space, reducable, reduced):
+ return space.bool_w(call_capi(space, 'add_type_reducer', [_ArgS(reducable), _ArgS(reduced)]))
+
def _c_base_offset(space, derived_h, base_h, address, direction):
- args = [_ArgH(derived_h), _ArgH(base_h), _ArgH(address), _ArgL(direction)]
+ args = [_ArgH(derived_h), _ArgH(base_h), _ArgO(address), _ArgI(direction)]
return _cdata_to_ptrdiff_t(space, call_capi(space, 'base_offset', args))
def c_base_offset(space, derived, base, address, direction):
if derived == base:
@@ -581,10 +647,9 @@ def c_base_offset1(space, derived_h, base, address, direction):
# method/function reflection information -------------------------------------
def c_num_methods(space, cppscope):
- args = [_ArgH(cppscope.handle)]
- return space.int_w(call_capi(space, 'num_methods', args))
+ return space.int_w(call_capi(space, 'num_methods', [_ArgC(cppscope)]))
def c_method_indices_from_name(space, cppscope, name):
- args = [_ArgH(cppscope.handle), _ArgS(name)]
+ args = [_ArgC(cppscope), _ArgS(name)]
indices = rffi.cast(C_INDEX_ARRAY,
_cdata_to_ptr(space, call_capi(space, 'method_indices_from_name', args)))
if not indices:
@@ -592,7 +657,7 @@ def c_method_indices_from_name(space, cppscope, name):
py_indices = []
i = 0
index = indices[i]
- while index != -1:
+ while index != rffi.cast(C_INDEX, -1):
i += 1
py_indices.append(index)
index = indices[i]
@@ -600,107 +665,128 @@ def c_method_indices_from_name(space, cppscope, name):
return py_indices
def c_get_method(space, cppscope, index):
- args = [_ArgH(cppscope.handle), _ArgU(index)]
- return rffi.cast(C_METHOD, space.uint_w(call_capi(space, 'get_method', args)))
+ args = [_ArgC(cppscope), _ArgU(index)]
+ return _cdata_to_intptr_t(space, call_capi(space, 'get_method', args))
def c_method_name(space, cppmeth):
- return charp2str_free(space, call_capi(space, 'method_name', [_ArgH(cppmeth)]))
+ return charp2str_free(space, call_capi(space, 'method_name', [_ArgM(cppmeth)]))
def c_method_full_name(space, cppmeth):
- return charp2str_free(space, call_capi(space, 'method_full_name', [_ArgH(cppmeth)]))
+ return charp2str_free(space, call_capi(space, 'method_full_name', [_ArgM(cppmeth)]))
def c_method_mangled_name(space, cppmeth):
- return charp2str_free(space, call_capi(space, 'method_mangled_name', [_ArgH(cppmeth)]))
+ return charp2str_free(space, call_capi(space, 'method_mangled_name', [_ArgM(cppmeth)]))
def c_method_result_type(space, cppmeth):
- return charp2str_free(space, call_capi(space, 'method_result_type', [_ArgH(cppmeth)]))
+ return charp2str_free(space, call_capi(space, 'method_result_type', [_ArgM(cppmeth)]))
def c_method_num_args(space, cppmeth):
- return space.int_w(call_capi(space, 'method_num_args', [_ArgH(cppmeth)]))
+ return space.int_w(call_capi(space, 'method_num_args', [_ArgM(cppmeth)]))
def c_method_req_args(space, cppmeth):
- return space.int_w(call_capi(space, 'method_req_args', [_ArgH(cppmeth)]))
+ return space.int_w(call_capi(space, 'method_req_args', [_ArgM(cppmeth)]))
def c_method_arg_name(space, cppmeth, arg_index):
- args = [_ArgH(cppmeth), _ArgL(arg_index)]
+ args = [_ArgM(cppmeth), _ArgI(arg_index)]
return charp2str_free(space, call_capi(space, 'method_arg_name', args))
def c_method_arg_type(space, cppmeth, arg_index):
- args = [_ArgH(cppmeth), _ArgL(arg_index)]
+ args = [_ArgM(cppmeth), _ArgI(arg_index)]
return charp2str_free(space, call_capi(space, 'method_arg_type', args))
def c_method_arg_default(space, cppmeth, arg_index):
- args = [_ArgH(cppmeth), _ArgL(arg_index)]
+ args = [_ArgM(cppmeth), _ArgI(arg_index)]
return charp2str_free(space, call_capi(space, 'method_arg_default', args))
def c_method_signature(space, cppmeth, show_formalargs=True):
- args = [_ArgH(cppmeth), _ArgL(show_formalargs)]
+ args = [_ArgM(cppmeth), _ArgI(show_formalargs)]
return charp2str_free(space, call_capi(space, 'method_signature', args))
def c_method_signature_max(space, cppmeth, show_formalargs, maxargs):
- args = [_ArgH(cppmeth), _ArgL(show_formalargs), _ArgL(maxargs)]
+ args = [_ArgM(cppmeth), _ArgI(show_formalargs), _ArgI(maxargs)]
return charp2str_free(space, call_capi(space, 'method_signature_max', args))
def c_method_prototype(space, cppscope, cppmeth, show_formalargs=True):
- args = [_ArgH(cppscope.handle), _ArgH(cppmeth), _ArgL(show_formalargs)]
+ args = [_ArgC(cppscope), _ArgM(cppmeth), _ArgI(show_formalargs)]
return charp2str_free(space, call_capi(space, 'method_prototype', args))
def c_is_const_method(space, cppmeth):
- return space.bool_w(call_capi(space, 'is_const_method', [_ArgH(cppmeth)]))
+ return space.bool_w(call_capi(space, 'is_const_method', [_ArgM(cppmeth)]))
def c_get_num_templated_methods(space, cppscope):
- return space.int_w(call_capi(space, 'get_num_templated_methods', [_ArgH(cppscope.handle)]))
+ return space.int_w(call_capi(space, 'get_num_templated_methods', [_ArgC(cppscope)]))
def c_get_templated_method_name(space, cppscope, index):
- args = [_ArgH(cppscope.handle), _ArgU(index)]
+ args = [_ArgC(cppscope), _ArgU(index)]
return charp2str_free(space, call_capi(space, 'get_templated_method_name', args))
+def c_is_templated_constructor(space, cppscope, index):
+ args = [_ArgC(cppscope), _ArgU(index)]
+ return space.bool_w(space, call_capi(space, 'is_templated_constructor', args))
def c_exists_method_template(space, cppscope, name):
- args = [_ArgH(cppscope.handle), _ArgS(name)]
+ args = [_ArgC(cppscope), _ArgS(name)]
return space.bool_w(call_capi(space, 'exists_method_template', args))
def c_method_is_template(space, cppscope, index):
- args = [_ArgH(cppscope.handle), _ArgU(index)]
+ args = [_ArgC(cppscope), _ArgU(index)]
return space.bool_w(call_capi(space, 'method_is_template', args))
def c_get_method_template(space, cppscope, name, proto):
- args = [_ArgH(cppscope.handle), _ArgS(name), _ArgS(proto)]
+ args = [_ArgC(cppscope), _ArgS(name), _ArgS(proto)]
return rffi.cast(C_METHOD, space.int_w(call_capi(space, 'get_method_template', args)))
def c_get_global_operator(space, nss, lc, rc, op):
if nss is not None:
- args = [_ArgH(nss.handle), _ArgH(lc.handle), _ArgH(rc.handle), _ArgS(op)]
- return rffi.cast(WLAVC_INDEX, space.uint_w(call_capi(space, 'get_global_operator', args)))
- return rffi.cast(WLAVC_INDEX, -1)
+ args = [_ArgC(nss), _ArgC(lc), _ArgC(rc), _ArgS(op)]
+ return rffi.cast(C_INDEX, space.uint_w(call_capi(space, 'get_global_operator', args)))
+ return rffi.cast(C_INDEX, -1)
# method properties ----------------------------------------------------------
def c_is_public_method(space, cppmeth):
- return space.bool_w(call_capi(space, 'is_public_method', [_ArgH(cppmeth)]))
+ return space.bool_w(call_capi(space, 'is_public_method', [_ArgM(cppmeth)]))
+def c_is_protected_method(space, cppmeth):
+ return space.bool_w(call_capi(space, 'is_protected_method', [_ArgM(cppmeth)]))
def c_is_constructor(space, cppmeth):
- return space.bool_w(call_capi(space, 'is_constructor', [_ArgH(cppmeth)]))
+ return space.bool_w(call_capi(space, 'is_constructor', [_ArgM(cppmeth)]))
def c_is_destructor(space, cppmeth):
- return space.bool_w(call_capi(space, 'is_destructor', [_ArgH(cppmeth)]))
+ return space.bool_w(call_capi(space, 'is_destructor', [_ArgM(cppmeth)]))
def c_is_staticmethod(space, cppmeth):
- return space.bool_w(call_capi(space, 'is_staticmethod', [_ArgH(cppmeth)]))
+ return space.bool_w(call_capi(space, 'is_staticmethod', [_ArgM(cppmeth)]))
# data member reflection information -----------------------------------------
def c_num_datamembers(space, cppscope):
- return space.int_w(call_capi(space, 'num_datamembers', [_ArgH(cppscope.handle)]))
+ return space.int_w(call_capi(space, 'num_datamembers', [_ArgC(cppscope)]))
def c_datamember_name(space, cppscope, datamember_index):
- args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
+ args = [_ArgC(cppscope), _ArgI(datamember_index)]
return charp2str_free(space, call_capi(space, 'datamember_name', args))
def c_datamember_type(space, cppscope, datamember_index):
- args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
- return charp2str_free(space, call_capi(space, 'datamember_type', args))
+ args = [_ArgC(cppscope), _ArgI(datamember_index)]
+ return charp2str_free(space, call_capi(space, 'datamember_type', args))
def c_datamember_offset(space, cppscope, datamember_index):
- args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
+ args = [_ArgC(cppscope), _ArgI(datamember_index)]
return _cdata_to_intptr_t(space, call_capi(space, 'datamember_offset', args))
def c_datamember_index(space, cppscope, name):
- args = [_ArgH(cppscope.handle), _ArgS(name)]
+ args = [_ArgC(cppscope), _ArgS(name)]
return space.int_w(call_capi(space, 'datamember_index', args))
# data member properties -----------------------------------------------------
def c_is_publicdata(space, cppscope, datamember_index):
- args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
+ args = [_ArgC(cppscope), _ArgU(datamember_index)]
return space.bool_w(call_capi(space, 'is_publicdata', args))
+def c_is_protecteddata(space, cppscope, datamember_index):
+ args = [_ArgC(cppscope), _ArgU(datamember_index)]
+ return space.bool_w(call_capi(space, 'is_protecteddata', args))
def c_is_staticdata(space, cppscope, datamember_index):
- args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
+ args = [_ArgC(cppscope), _ArgU(datamember_index)]
return space.bool_w(call_capi(space, 'is_staticdata', args))
def c_is_const_data(space, cppscope, datamember_index):
- args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
+ args = [_ArgC(cppscope), _ArgU(datamember_index)]
return space.bool_w(call_capi(space, 'is_const_data', args))
def c_is_enum_data(space, cppscope, datamember_index):
- args = [_ArgH(cppscope.handle), _ArgL(datamember_index)]
+ args = [_ArgC(cppscope), _ArgU(datamember_index)]
return space.bool_w(call_capi(space, 'is_enum_data', args))
def c_get_dimension_size(space, cppscope, datamember_index, dim_idx):
- args = [_ArgH(cppscope.handle), _ArgL(datamember_index), _ArgL(dim_idx)]
+ args = [_ArgC(cppscope), _ArgU(datamember_index), _ArgI(dim_idx)]
return space.int_w(call_capi(space, 'get_dimension_size', args))
+# enum properties ------------------------------------------------------------
+def c_get_enum(space, cppscope, name):
+ args = [_ArgC(cppscope), _ArgS(name)]
+ return _cdata_to_cenum(call_capi(space, 'get_enum', args))
+def c_num_enum_data(space, cppenum):
+ return space.int_w(call_capi(space, 'num_enum_data', [_ArgE(cppenum)]))
+def c_get_enum_data_name(space, cppenum, idata):
+ args = [_ArgE(cppenum), _ArgU(idata)]
+ return charp2str_free(space, call_capi(space, 'get_enum_data_name', args))
+def c_get_enum_data_value(space, cppenum, idata):
+ args = [_ArgE(cppenum), _ArgU(idata)]
+ return rffi.cast(C_ENUM, call_capi(space, 'get_enum_data_value', args))
+
# misc helpers ---------------------------------------------------------------
def c_strtoll(space, svalue):
return space.r_longlong_w(call_capi(space, 'strtoll', [_ArgS(svalue)]))
@@ -717,18 +803,18 @@ def charp2str_free(space, cdata):
def c_charp2stdstring(space, svalue, sz):
return _cdata_to_cobject(space, call_capi(space, 'charp2stdstring',
- [_ArgS(svalue), _ArgH(rffi.cast(rffi.ULONG, sz))]))
+ [_ArgS(svalue), _ArgU(rffi.cast(C_INDEX, sz))]))
def c_stdstring2charp(space, cppstr):
- sz = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw')
+ szp = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw')
try:
w_cstr = call_capi(space, 'stdstring2charp',
- [_ArgH(cppstr), _ArgP(rffi.cast(rffi.VOIDP, sz))])
- cstr_len = int(intmask(sz[0]))
+ [_ArgO(cppstr), _ArgP(rffi.cast(rffi.VOIDP, szp))])
+ cstr_len = int(intmask(szp[0]))
finally:
- lltype.free(sz, flavor='raw')
+ lltype.free(szp, flavor='raw')
return rffi.charpsize2str(_cdata_to_ccharp(space, w_cstr), cstr_len)
-def c_stdstring2stdstring(space, cppobject):
- return _cdata_to_cobject(space, call_capi(space, 'stdstring2stdstring', [_ArgH(cppobject)]))
+def c_stdstring2stdstring(space, cppobj):
+ return _cdata_to_cobject(space, call_capi(space, 'stdstring2stdstring', [_ArgO(cppobj)]))
def c_longdouble2double(space, addr):
return space.float_w(call_capi(space, 'longdouble2double', [_ArgP(addr)]))
@@ -736,9 +822,9 @@ def c_double2longdouble(space, dval, addr):
call_capi(space, 'double2longdouble', [_ArgD(dval), _ArgP(addr)])
def c_vectorbool_getitem(space, vbool, idx):
- return call_capi(space, 'vectorbool_getitem', [_ArgH(vbool), _ArgL(idx)])
+ return call_capi(space, 'vectorbool_getitem', [_ArgO(vbool), _ArgI(idx)])
def c_vectorbool_setitem(space, vbool, idx, value):
- call_capi(space, 'vectorbool_setitem', [_ArgH(vbool), _ArgL(idx), _ArgL(value)])
+ call_capi(space, 'vectorbool_setitem', [_ArgO(vbool), _ArgI(idx), _ArgI(value)])
# TODO: factor these out ...
diff --git a/pypy/module/_cppyy/converter.py b/pypy/module/_cppyy/converter.py
index 4a9b6ffd57..897715288a 100644
--- a/pypy/module/_cppyy/converter.py
+++ b/pypy/module/_cppyy/converter.py
@@ -144,10 +144,10 @@ class ArrayTypeConverterMixin(object):
def from_memory(self, space, w_obj, offset):
# read access, so no copy needed
- address_value = self._get_raw_address(space, w_obj, offset)
- address = rffi.cast(rffi.ULONG, address_value)
+ address = self._get_raw_address(space, w_obj, offset)
+ ipv = rffi.cast(rffi.UINTPTR_T, address)
return lowlevelviews.W_LowLevelView(
- space, letter2tp(space, self.typecode), self.size, address)
+ space, letter2tp(space, self.typecode), self.size, ipv)
def to_memory(self, space, w_obj, w_value, offset):
# copy the full array (uses byte copy for now)
@@ -157,7 +157,6 @@ class ArrayTypeConverterMixin(object):
for i in range(min(self.size*self.typesize, buf.getlength())):
address[i] = buf.getitem(i)
-
class PtrTypeConverterMixin(object):
_mixin_ = True
_immutable_fields_ = ['size']
@@ -186,10 +185,10 @@ class PtrTypeConverterMixin(object):
def from_memory(self, space, w_obj, offset):
# read access, so no copy needed
- address_value = self._get_raw_address(space, w_obj, offset)
- address = rffi.cast(rffi.ULONGP, address_value)
+ address = self._get_raw_address(space, w_obj, offset)
+ ipv = rffi.cast(rffi.UINTPTR_T, rffi.cast(rffi.VOIDPP, address)[0])
return lowlevelviews.W_LowLevelView(
- space, letter2tp(space, self.typecode), self.size, address[0])
+ space, letter2tp(space, self.typecode), self.size, ipv)
def to_memory(self, space, w_obj, w_value, offset):
# copy only the pointer value
@@ -202,6 +201,13 @@ class PtrTypeConverterMixin(object):
raise oefmt(space.w_TypeError,
"raw buffer interface not supported")
+class ArrayPtrTypeConverterMixin(PtrTypeConverterMixin):
+ _mixin_ = True
+
+ def cffi_type(self, space):
+ state = space.fromcache(ffitypes.State)
+ return state.c_voidpp
+
class NumericTypeConverterMixin(object):
_mixin_ = True
@@ -300,9 +306,12 @@ class BoolConverter(ffitypes.typeid(bool), TypeConverter):
else:
address[0] = '\x00'
-class CharConverter(ffitypes.typeid(rffi.CHAR), TypeConverter):
+
+class CharTypeConverterMixin(object):
+ _mixin_ = True
+
def convert_argument(self, space, w_obj, address):
- x = rffi.cast(rffi.CCHARP, address)
+ x = rffi.cast(self.c_ptrtype, address)
x[0] = self._unwrap_object(space, w_obj)
ba = rffi.cast(rffi.CCHARP, address)
ba[capi.c_function_arg_typeoffset(space)] = 'b'
@@ -312,17 +321,14 @@ class CharConverter(ffitypes.typeid(rffi.CHAR), TypeConverter):
x[0] = self._unwrap_object(space, w_obj)
def from_memory(self, space, w_obj, offset):
- address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset))
- return space.newbytes(address[0])
+ address = rffi.cast(self.c_ptrtype, self._get_raw_address(space, w_obj, offset))
+ return self._wrap_object(space, address[0])
def to_memory(self, space, w_obj, w_value, offset):
- address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset))
+ address = rffi.cast(self.c_ptrtype, self._get_raw_address(space, w_obj, offset))
address[0] = self._unwrap_object(space, w_value)
-class UCharConverter(ffitypes.typeid(rffi.UCHAR), CharConverter):
- pass
-
class FloatConverter(ffitypes.typeid(rffi.FLOAT), FloatTypeConverterMixin, TypeConverter):
_immutable_fields_ = ['default', 'valid_default']
@@ -413,9 +419,9 @@ class ConstLongDoubleRefConverter(ConstRefNumericTypeConverterMixin, LongDoubleC
class CStringConverter(TypeConverter):
def convert_argument(self, space, w_obj, address):
- x = rffi.cast(rffi.LONGP, address)
+ x = rffi.cast(rffi.VOIDPP, address)
arg = space.text_w(w_obj)
- x[0] = rffi.cast(rffi.LONG, rffi.str2charp(arg))
+ x[0] = rffi.cast(rffi.VOIDP, rffi.str2charp(arg))
ba = rffi.cast(rffi.CCHARP, address)
ba[capi.c_function_arg_typeoffset(space)] = 'p'
@@ -470,12 +476,12 @@ class VoidPtrConverter(TypeConverter):
# returned as a long value for the address (INTPTR_T is not proper
# per se, but rffi does not come with a PTRDIFF_T)
address = self._get_raw_address(space, w_obj, offset)
- ptrval = rffi.cast(rffi.ULONGP, address)[0]
- if ptrval == rffi.cast(rffi.ULONG, 0):
+ ipv = rffi.cast(rffi.UINTPTR_T, rffi.cast(rffi.VOIDPP, address)[0])
+ if ipv == rffi.cast(rffi.UINTPTR_T, 0):
from pypy.module._cppyy import interp_cppyy
return interp_cppyy.get_nullptr(space)
shape = letter2tp(space, 'P')
- return lowlevelviews.W_LowLevelView(space, shape, sys.maxint/shape.size, ptrval)
+ return lowlevelviews.W_LowLevelView(space, shape, sys.maxint/shape.size, ipv)
def to_memory(self, space, w_obj, w_value, offset):
address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset))
@@ -584,7 +590,10 @@ class InstanceConverter(InstanceRefConverter):
return interp_cppyy.wrap_cppinstance(space, address, self.clsdecl, do_cast=False)
def to_memory(self, space, w_obj, w_value, offset):
- self._is_abstract(space)
+ address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
+ assign = self.clsdecl.get_overload("__assign__")
+ from pypy.module._cppyy import interp_cppyy
+ assign.call_impl(address, [w_value])
class InstancePtrConverter(InstanceRefConverter):
typecode = 'o'
@@ -601,7 +610,28 @@ class InstancePtrConverter(InstanceRefConverter):
def from_memory(self, space, w_obj, offset):
address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
from pypy.module._cppyy import interp_cppyy
- return interp_cppyy.wrap_cppinstance(space, address, self.clsdecl, do_cast=False)
+ return interp_cppyy.wrap_cppinstance(
+ space, address, self.clsdecl, do_cast=False, is_ref=True)
+
+ def to_memory(self, space, w_obj, w_value, offset):
+ from pypy.module._cppyy.interp_cppyy import W_CPPInstance
+ cppinstance = space.interp_w(W_CPPInstance, w_value, can_be_None=True)
+ if cppinstance:
+ # get the object address from value, correct for hierarchy offset
+ rawobject = cppinstance.get_rawobject()
+ base_offset = capi.c_base_offset(space, cppinstance.clsdecl, self.clsdecl, rawobject, 1)
+ rawptr = capi.direct_ptradd(rawobject, base_offset)
+
+ # get the data member address and write the pointer in
+ address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset))
+ address[0] = rffi.cast(rffi.VOIDP, rawptr)
+
+ # register the value object for potential recycling
+ from pypy.module._cppyy.interp_cppyy import memory_regulator
+ memory_regulator.register(cppinstance)
+ else:
+ raise oefmt(space.w_TypeError,
+ "cannot pass %T instance as %s", w_value, self.clsdecl.name)
class InstancePtrPtrConverter(InstancePtrConverter):
typecode = 'o'
@@ -625,29 +655,10 @@ class InstancePtrPtrConverter(InstancePtrConverter):
raise FastCallNotPossible
def from_memory(self, space, w_obj, offset):
- address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
- from pypy.module._cppyy import interp_cppyy
- return interp_cppyy.wrap_cppinstance(
- space, address, self.clsdecl, do_cast=False, is_ref=True)
+ self._is_abstract(space)
def to_memory(self, space, w_obj, w_value, offset):
- # the actual data member is of object* type, but we receive a pointer to that
- # data member in order to modify its value, so by convention, the internal type
- # used is object**
- address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset))
- from pypy.module._cppyy.interp_cppyy import W_CPPInstance
- cppinstance = space.interp_w(W_CPPInstance, w_value, can_be_None=True)
- if cppinstance:
- rawobject = cppinstance.get_rawobject()
- offset = capi.c_base_offset(space, cppinstance.clsdecl, self.clsdecl, rawobject, 1)
- obj_address = capi.direct_ptradd(rawobject, offset)
- address[0] = rffi.cast(rffi.VOIDP, obj_address);
- # register the value for potential recycling
- from pypy.module._cppyy.interp_cppyy import memory_regulator
- memory_regulator.register(cppinstance)
- else:
- raise oefmt(space.w_TypeError,
- "cannot pass %T instance as %s", w_value, self.clsdecl.name)
+ self._is_abstract(space)
def finalize_call(self, space, w_obj):
if self.ref_buffer:
@@ -678,7 +689,7 @@ class InstanceArrayConverter(InstancePtrConverter):
self._is_abstract(space)
-class StdStringConverter(InstanceConverter):
+class STLStringConverter(InstanceConverter):
def __init__(self, space, extra):
from pypy.module._cppyy import interp_cppyy
cppclass = interp_cppyy.scope_byname(space, capi.std_string_name)
@@ -689,22 +700,12 @@ class StdStringConverter(InstanceConverter):
if isinstance(w_obj, W_CPPInstance):
arg = InstanceConverter._unwrap_object(self, space, w_obj)
return capi.c_stdstring2stdstring(space, arg)
- else:
- return capi.c_charp2stdstring(space, space.text_w(w_obj), space.len_w(w_obj))
-
- def to_memory(self, space, w_obj, w_value, offset):
- try:
- address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
- assign = self.clsdecl.get_overload("__assign__")
- from pypy.module._cppyy import interp_cppyy
- assign.call_impl(address, [w_value])
- except Exception:
- InstanceConverter.to_memory(self, space, w_obj, w_value, offset)
+ return capi.c_charp2stdstring(space, space.text_w(w_obj), space.len_w(w_obj))
def free_argument(self, space, arg):
capi.c_destruct(space, self.clsdecl, rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, arg)[0]))
-class StdStringMoveConverter(StdStringConverter):
+class STLStringMoveConverter(STLStringConverter):
def _unwrap_object(self, space, w_obj):
# moving is same as by-ref, but have to check that move is allowed
moveit_reason = 3
@@ -721,7 +722,7 @@ class StdStringMoveConverter(StdStringConverter):
if moveit_reason:
try:
- return StdStringConverter._unwrap_object(self, space, w_obj)
+ return STLStringConverter._unwrap_object(self, space, w_obj)
except Exception:
if moveit_reason == 1:
# TODO: if the method fails on some other converter, then the next
@@ -732,7 +733,7 @@ class StdStringMoveConverter(StdStringConverter):
raise oefmt(space.w_ValueError, "object is not an rvalue")
-class StdStringRefConverter(InstancePtrConverter):
+class STLStringRefConverter(InstancePtrConverter):
_immutable_fields_ = ['cppclass', 'typecode']
typecode = 'V'
@@ -887,9 +888,14 @@ def get_converter(space, _name, default):
# 3a) smart pointers
# 4) void* or void converter (which fails on use)
- name = capi.c_resolve_name(space, _name)
+ # original, exact match
+ try:
+ return _converters[_name](space, default)
+ except KeyError:
+ pass
- # full, exact match
+ # resolved, exact match
+ name = capi.c_resolve_name(space, _name)
try:
return _converters[name](space, default)
except KeyError:
@@ -960,16 +966,17 @@ def get_converter(space, _name, default):
return InstanceArrayConverter(space, clsdecl, array_size, dims)
elif cpd == "":
return InstanceConverter(space, clsdecl)
- elif "(anonymous)" in name:
+
+ if "(anonymous)" in name:
# special case: enum w/o a type name
- return _converters["internal_enum_type_t"](space, default)
+ return _converters["internal_enum_type_t"+cpd](space, default)
elif "(*)" in name or "::*)" in name:
# function pointer
pos = name.find("*)")
if pos > 0:
return FunctionPointerConverter(space, name[pos+2:])
- # void* or void converter (which fails on use)
+ # void*|**|*& or void converter (which fails on use)
if 0 <= cpd.find('*'):
return VoidPtrConverter(space, default) # "user knows best"
@@ -979,8 +986,6 @@ def get_converter(space, _name, default):
_converters["bool"] = BoolConverter
-_converters["char"] = CharConverter
-_converters["unsigned char"] = UCharConverter
_converters["float"] = FloatConverter
_converters["const float&"] = ConstFloatRefConverter
_converters["double"] = DoubleConverter
@@ -992,11 +997,11 @@ _converters["void*"] = VoidPtrConverter
_converters["void**"] = VoidPtrPtrConverter
_converters["void*&"] = VoidPtrRefConverter
-# special cases (note: 'string' aliases added below)
-_converters["std::string"] = StdStringConverter
-_converters["const std::basic_string<char>&"] = StdStringConverter # TODO: shouldn't copy
-_converters["std::basic_string<char>&"] = StdStringRefConverter
-_converters["std::basic_string<char>&&"] = StdStringMoveConverter
+# special cases (note: 'std::string' aliases added below)
+_converters["std::basic_string<char>"] = STLStringConverter
+_converters["const std::basic_string<char>&"] = STLStringConverter # TODO: shouldn't copy
+_converters["std::basic_string<char>&"] = STLStringRefConverter
+_converters["std::basic_string<char>&&"] = STLStringMoveConverter
_converters["PyObject*"] = PyObjectConverter
@@ -1005,71 +1010,57 @@ _converters["#define"] = MacroConverter
# add basic (builtin) converters
def _build_basic_converters():
"NOT_RPYTHON"
- # signed types (use strtoll in setting of default in __init__)
- type_info = (
- (rffi.SHORT, ("short", "short int"), 'h'),
- (rffi.INT, ("int", "internal_enum_type_t"), 'i'),
- )
-
- # constref converters exist only b/c the stubs take constref by value, whereas
- # libffi takes them by pointer (hence it needs the fast-path in testing); note
- # that this is list is not complete, as some classes are specialized
-
- for c_type, names, c_tc in type_info:
- class BasicConverter(ffitypes.typeid(c_type), IntTypeConverterMixin, TypeConverter):
+ # basic char types
+ type_info = {
+ (rffi.CHAR, "char"),
+ (rffi.SIGNEDCHAR, "signed char"),
+ (rffi.UCHAR, "unsigned char"),
+ (lltype.UniChar, "wchar_t"),
+ (ffitypes.CHAR16_T, "char16_t"),
+ (ffitypes.CHAR32_T, "char32_t"),
+ }
+
+ for c_type, name in type_info:
+ class BasicConverter(ffitypes.typeid(c_type), CharTypeConverterMixin, TypeConverter):
_immutable_ = True
- typecode = c_tc
def __init__(self, space, default):
self.valid_default = False
try:
- self.default = rffi.cast(self.c_type, capi.c_strtoll(space, default))
+ self.default = rffi.cast(self.c_type, capi.c_strtoull(space, default))
self.valid_default = True
except Exception:
self.default = rffi.cast(self.c_type, 0)
class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
_immutable_ = True
- for name in names:
- _converters[name] = BasicConverter
- _converters["const "+name+"&"] = ConstRefConverter
+ _converters[name] = BasicConverter
+ _converters["const "+name+"&"] = ConstRefConverter
+ # signed types use strtoll in setting of default in __init__, unsigned uses strtoull
type_info = (
- (rffi.LONG, ("long", "long int"), 'l'),
- (rffi.LONGLONG, ("long long", "long long int", "Long64_t"), 'q'),
+ (ffitypes.INT8_T, ("int8_t",), 'b', capi.c_strtoll),
+ (ffitypes.UINT8_T, ("uint8_t", "std::byte", "byte"), 'B', capi.c_strtoull),
+ (rffi.SHORT, ("short", "short int"), 'h', capi.c_strtoll),
+ (rffi.USHORT, ("unsigned short", "unsigned short int"), 'H', capi.c_strtoull),
+ (rffi.INT, ("int", "internal_enum_type_t"), 'i', capi.c_strtoll),
+ (rffi.UINT, ("unsigned", "unsigned int"), 'I', capi.c_strtoull),
+ (rffi.LONG, ("long", "long int"), 'l', capi.c_strtoll),
+ (rffi.ULONG, ("unsigned long", "unsigned long int"), 'L', capi.c_strtoull),
+ (rffi.LONGLONG, ("long long", "long long int", "Long64_t"), 'q', capi.c_strtoll),
+ (rffi.ULONGLONG, ("unsigned long long", "unsigned long long int", "ULong64_t"), 'Q', capi.c_strtoull),
)
- for c_type, names, c_tc in type_info:
- class BasicConverter(ffitypes.typeid(c_type), IntTypeConverterMixin, TypeConverter):
- _immutable_ = True
- typecode = c_tc
- def __init__(self, space, default):
- self.valid_default = False
- try:
- self.default = rffi.cast(self.c_type, capi.c_strtoll(space, default))
- self.valid_default = True
- except Exception:
- self.default = rffi.cast(self.c_type, 0)
- class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
- _immutable_ = True
- for name in names:
- _converters[name] = BasicConverter
- _converters["const "+name+"&"] = ConstRefConverter
-
- # unsigned integer types (use strtoull in setting of default in __init__)
- type_info = (
- (rffi.USHORT, ("unsigned short", "unsigned short int"), 'H'),
- (rffi.UINT, ("unsigned", "unsigned int"), 'I'),
- (rffi.ULONG, ("unsigned long", "unsigned long int"), 'L'),
- (rffi.ULONGLONG, ("unsigned long long", "unsigned long long int", "ULong64_t"), 'Q'),
- )
+ # constref converters exist only b/c the stubs take constref by value, whereas
+ # libffi takes them by pointer (hence it needs the fast-path in testing); note
+ # that this is list is not complete, as some classes are specialized
- for c_type, names, c_tc in type_info:
+ for c_type, names, c_tc, dfc in type_info:
class BasicConverter(ffitypes.typeid(c_type), IntTypeConverterMixin, TypeConverter):
_immutable_ = True
typecode = c_tc
def __init__(self, space, default):
self.valid_default = False
try:
- self.default = rffi.cast(self.c_type, capi.c_strtoull(space, default))
+ self.default = rffi.cast(self.c_type, dfc(space, default))
self.valid_default = True
except Exception:
self.default = rffi.cast(self.c_type, 0)
@@ -1085,8 +1076,9 @@ _build_basic_converters()
def _build_array_converters():
"NOT_RPYTHON"
array_info = (
- ('b', rffi.sizeof(rffi.UCHAR), ("bool",)), # is debatable, but works ...
- ('B', rffi.sizeof(rffi.UCHAR), ("unsigned char",)),
+ ('b', rffi.sizeof(rffi.SIGNEDCHAR), ("bool",)), # is debatable, but works ...
+ ('b', rffi.sizeof(rffi.SIGNEDCHAR), ("signed char",)),
+ ('B', rffi.sizeof(rffi.UCHAR), ("unsigned char", "std::byte", "byte")),
('h', rffi.sizeof(rffi.SHORT), ("short int", "short")),
('H', rffi.sizeof(rffi.USHORT), ("unsigned short int", "unsigned short")),
('i', rffi.sizeof(rffi.INT), ("int",)),
@@ -1109,9 +1101,14 @@ def _build_array_converters():
_immutable_fields_ = ['typecode', 'typesize']
typecode = tcode
typesize = tsize
+ class ArrayPtrConverter(ArrayPtrTypeConverterMixin, TypeConverter):
+ _immutable_fields_ = ['typecode', 'typesize']
+ typecode = tcode
+ typesize = tsize
for name in names:
_a_converters[name+'[]'] = ArrayConverter
_a_converters[name+'*'] = PtrConverter
+ _a_converters[name+'**'] = ArrayPtrConverter
# special case, const char* w/ size and w/o '\0'
_a_converters["const char[]"] = CStringConverterWithSize
@@ -1123,14 +1120,14 @@ _build_array_converters()
def _add_aliased_converters():
"NOT_RPYTHON"
aliases = (
- ("char", "signed char"), # TODO: check
("const char*", "char*"),
- ("std::string", "string"),
- ("std::string", "std::basic_string<char>"),
- ("const std::basic_string<char>&", "const string&"),
- ("std::basic_string<char>&", "string&"),
- ("std::basic_string<char>&&", "string&&"),
+ ("std::basic_string<char>", "std::string"),
+ ("const std::basic_string<char>&", "const std::string&"),
+ ("std::basic_string<char>&", "std::string&"),
+ ("std::basic_string<char>&&", "std::string&&"),
+
+ ("const internal_enum_type_t&", "internal_enum_type_t&"),
("PyObject*", "_object*"),
)
diff --git a/pypy/module/_cppyy/executor.py b/pypy/module/_cppyy/executor.py
index 73de224170..2f9b21dfb3 100644
--- a/pypy/module/_cppyy/executor.py
+++ b/pypy/module/_cppyy/executor.py
@@ -1,8 +1,12 @@
import sys
from pypy.interpreter.error import oefmt
+from pypy.interpreter.argument import Arguments
+from pypy.objspace.std.unicodeobject import W_UnicodeObject
+
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib import jit_libffi
+
from pypy.module._rawffi.interp_rawffi import letter2tp
from pypy.module._cppyy import helper, capi, ffitypes, lowlevelviews
@@ -34,7 +38,7 @@ class Executor(object):
raise oefmt(space.w_TypeError,
"return type not available or supported")
- def execute_libffi(self, space, cif_descr, funcaddr, buffer):
+ def execute_libffi(self, space, cif_descr, funcaddr, buf):
from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
raise FastCallNotPossible
@@ -50,13 +54,13 @@ class PtrTypeExecutor(Executor):
def execute(self, space, cppmethod, cppthis, num_args, args):
if hasattr(space, "fake"):
raise NotImplementedError
- lresult = capi.c_call_l(space, cppmethod, cppthis, num_args, args)
- ptrval = rffi.cast(rffi.ULONG, lresult)
- if ptrval == rffi.cast(rffi.ULONG, 0):
+ address = capi.c_call_r(space, cppmethod, cppthis, num_args, args)
+ ipv = rffi.cast(rffi.UINTPTR_T, address)
+ if ipv == rffi.cast(rffi.UINTPTR_T, 0):
from pypy.module._cppyy import interp_cppyy
return interp_cppyy.get_nullptr(space)
shape = letter2tp(space, self.typecode)
- return lowlevelviews.W_LowLevelView(space, shape, sys.maxint/shape.size, ptrval)
+ return lowlevelviews.W_LowLevelView(space, shape, sys.maxint/shape.size, ipv)
class VoidExecutor(Executor):
@@ -68,8 +72,8 @@ class VoidExecutor(Executor):
capi.c_call_v(space, cppmethod, cppthis, num_args, args)
return space.w_None
- def execute_libffi(self, space, cif_descr, funcaddr, buffer):
- jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
+ def execute_libffi(self, space, cif_descr, funcaddr, buf):
+ jit_libffi.jit_ffi_call(cif_descr, funcaddr, buf)
return space.w_None
@@ -80,9 +84,9 @@ class NumericExecutorMixin(object):
result = self.c_stubcall(space, cppmethod, cppthis, num_args, args)
return self._wrap_object(space, rffi.cast(self.c_type, result))
- def execute_libffi(self, space, cif_descr, funcaddr, buffer):
- jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
- result = rffi.ptradd(buffer, cif_descr.exchange_result)
+ def execute_libffi(self, space, cif_descr, funcaddr, buf):
+ jit_libffi.jit_ffi_call(cif_descr, funcaddr, buf)
+ result = rffi.ptradd(buf, cif_descr.exchange_result)
return self._wrap_object(space, rffi.cast(self.c_ptrtype, result)[0])
class NumericRefExecutorMixin(object):
@@ -107,9 +111,9 @@ class NumericRefExecutorMixin(object):
result = capi.c_call_r(space, cppmethod, cppthis, num_args, args)
return self._wrap_reference(space, rffi.cast(self.c_ptrtype, result))
- def execute_libffi(self, space, cif_descr, funcaddr, buffer):
- jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
- result = rffi.ptradd(buffer, cif_descr.exchange_result)
+ def execute_libffi(self, space, cif_descr, funcaddr, buf):
+ jit_libffi.jit_ffi_call(cif_descr, funcaddr, buf)
+ result = rffi.ptradd(buf, cif_descr.exchange_result)
return self._wrap_reference(space,
rffi.cast(self.c_ptrtype, rffi.cast(rffi.VOIDPP, result)[0]))
@@ -121,7 +125,7 @@ class LongDoubleExecutorMixin(object):
result = self.c_stubcall(space, cppmethod, cppthis, num_args, args)
return space.newfloat(result)
- def execute_libffi(self, space, cif_descr, funcaddr, buffer):
+ def execute_libffi(self, space, cif_descr, funcaddr, buf):
from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
raise FastCallNotPossible
@@ -144,9 +148,9 @@ class LongDoubleRefExecutorMixin(NumericRefExecutorMixin):
result = capi.c_call_r(space, cppmethod, cppthis, num_args, args)
return self._wrap_reference(space, rffi.cast(self.c_ptrtype, result))
- def execute_libffi(self, space, cif_descr, funcaddr, buffer):
- jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
- result = rffi.ptradd(buffer, cif_descr.exchange_result)
+ def execute_libffi(self, space, cif_descr, funcaddr, buf):
+ jit_libffi.jit_ffi_call(cif_descr, funcaddr, buf)
+ result = rffi.ptradd(buf, cif_descr.exchange_result)
return self._wrap_reference(space,
rffi.cast(self.c_ptrtype, rffi.cast(rffi.VOIDPP, result)[0]))
@@ -158,12 +162,34 @@ class LongDoubleRefExecutor(ffitypes.typeid(rffi.LONGDOUBLE), LongDoubleRefExecu
class CStringExecutor(Executor):
def execute(self, space, cppmethod, cppthis, num_args, args):
- lresult = capi.c_call_l(space, cppmethod, cppthis, num_args, args)
- ccpresult = rffi.cast(rffi.CCHARP, lresult)
- if ccpresult == rffi.cast(rffi.CCHARP, 0):
+ vptr = capi.c_call_r(space, cppmethod, cppthis, num_args, args)
+ ccp = rffi.cast(rffi.CCHARP, vptr)
+ if ccp == rffi.cast(rffi.CCHARP, 0):
return space.newbytes("")
- result = rffi.charp2str(ccpresult) # TODO: make it a choice to free
- return space.newbytes(result)
+ result = rffi.charp2str(ccp) # TODO: make it a choice to free
+ return space.newtext(result)
+
+
+class CharNExecutor(object):
+ _mixin_ = True
+ def execute(self, space, cppmethod, cppthis, num_args, args):
+ lres = capi.c_call_l(space, cppmethod, cppthis, num_args, args)
+ return self._wrap_object(space, lres)
+
+ def execute_libffi(self, space, cif_descr, funcaddr, buf):
+ jit_libffi.jit_ffi_call(cif_descr, funcaddr, buf)
+ vptr = rffi.ptradd(buf, cif_descr.exchange_result)
+ lres = rffi.cast(rffi.LONG, rffi.cast(rffi.LONGP, vptr)[0])
+ return self._wrap_object(space, lres)
+
+class WCharExecutor(ffitypes.typeid(lltype.UniChar), CharNExecutor, Executor):
+ pass
+
+class Char16Executor(ffitypes.typeid(ffitypes.CHAR16_T), CharNExecutor, Executor):
+ pass
+
+class Char32Executor(ffitypes.typeid(ffitypes.CHAR32_T), CharNExecutor, Executor):
+ pass
class ConstructorExecutor(Executor):
@@ -175,7 +201,7 @@ class ConstructorExecutor(Executor):
class InstanceExecutor(Executor):
- # For return of a C++ instance by pointer: MyClass* func()
+ # For return of a C++ instance by value: MyClass func()
_immutable_fields_ = ['clsdecl']
def __init__(self, space, clsdecl):
@@ -204,12 +230,12 @@ class InstancePtrExecutor(InstanceExecutor):
return interp_cppyy.wrap_cppinstance(space, obj, self.clsdecl)
def execute(self, space, cppmethod, cppthis, num_args, args):
- lresult = capi.c_call_l(space, cppmethod, cppthis, num_args, args)
- return self._wrap_result(space, rffi.cast(capi.C_OBJECT, lresult))
+ vptr = capi.c_call_r(space, cppmethod, cppthis, num_args, args)
+ return self._wrap_result(space, rffi.cast(capi.C_OBJECT, vptr))
- def execute_libffi(self, space, cif_descr, funcaddr, buffer):
- jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
- presult = rffi.ptradd(buffer, cif_descr.exchange_result)
+ def execute_libffi(self, space, cif_descr, funcaddr, buf):
+ jit_libffi.jit_ffi_call(cif_descr, funcaddr, buf)
+ presult = rffi.ptradd(buf, cif_descr.exchange_result)
obj = rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, presult)[0])
return self._wrap_result(space, obj)
@@ -218,14 +244,46 @@ class InstancePtrPtrExecutor(InstancePtrExecutor):
def execute(self, space, cppmethod, cppthis, num_args, args):
presult = capi.c_call_r(space, cppmethod, cppthis, num_args, args)
- ref = rffi.cast(rffi.VOIDPP, presult)
- return self._wrap_result(space, rffi.cast(capi.C_OBJECT, ref[0]))
+ vref = rffi.cast(rffi.VOIDPP, presult)
+ return self._wrap_result(space, rffi.cast(capi.C_OBJECT, vref[0]))
- def execute_libffi(self, space, cif_descr, funcaddr, buffer):
+ def execute_libffi(self, space, cif_descr, funcaddr, buf):
from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
raise FastCallNotPossible
+class ComplexExecutor(Executor):
+ _immutable_fields_ = ['clsdecl', 'realf', 'imagf']
+
+ def __init__(self, space, clsdecl):
+ Executor.__init__(self, space, clsdecl)
+ self.clsdecl = clsdecl
+ self.realf = self.clsdecl.scope__dispatch__('real', '')
+ self.imagf = self.clsdecl.scope__dispatch__('imag', '')
+
+ def _convert2complex(self, space, cmplx):
+ w_real = self.realf.call_impl(cmplx, [])
+ w_imag = self.imagf.call_impl(cmplx, [])
+ return space.newcomplex(space.float_w(w_real), space.float_w(w_imag))
+
+ def execute(self, space, cppmethod, cppthis, num_args, args):
+ cmplx = capi.c_call_o(space, cppmethod, cppthis, num_args, args, self.clsdecl)
+ pycmplx = self._convert2complex(space, rffi.cast(capi.C_OBJECT, cmplx))
+ capi.c_destruct(space, self.clsdecl, cmplx)
+ return pycmplx
+
+class ComplexRefExecutor(ComplexExecutor):
+ def execute(self, space, cppmethod, cppthis, num_args, args):
+ cmplx = capi.c_call_r(space, cppmethod, cppthis, num_args, args)
+ return self._convert2complex(space, rffi.cast(capi.C_OBJECT, cmplx))
+
+ def execute_libffi(self, space, cif_descr, funcaddr, buf):
+ jit_libffi.jit_ffi_call(cif_descr, funcaddr, buf)
+ result = rffi.ptradd(buf, cif_descr.exchange_result)
+ return self._convert2complex(space,
+ rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, result)[0]))
+
+
class StdStringExecutor(InstancePtrExecutor):
def execute(self, space, cppmethod, cppthis, num_args, args):
cstr, cstr_len = capi.c_call_s(space, cppmethod, cppthis, num_args, args)
@@ -233,7 +291,7 @@ class StdStringExecutor(InstancePtrExecutor):
capi.c_free(space, rffi.cast(rffi.VOIDP, cstr))
return space.newbytes(pystr)
- def execute_libffi(self, space, cif_descr, funcaddr, buffer):
+ def execute_libffi(self, space, cif_descr, funcaddr, buf):
from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
raise FastCallNotPossible
@@ -257,15 +315,15 @@ class PyObjectExecutor(PtrTypeExecutor):
def execute(self, space, cppmethod, cppthis, num_args, args):
if hasattr(space, "fake"):
raise NotImplementedError
- lresult = capi.c_call_l(space, cppmethod, cppthis, num_args, args)
- return self.wrap_result(space, lresult)
+ vptr = capi.c_call_r(space, cppmethod, cppthis, num_args, args)
+ return self.wrap_result(space, vptr)
- def execute_libffi(self, space, cif_descr, funcaddr, buffer):
+ def execute_libffi(self, space, cif_descr, funcaddr, buf):
if hasattr(space, "fake"):
raise NotImplementedError
- jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
- result = rffi.ptradd(buffer, cif_descr.exchange_result)
- return self.wrap_result(space, rffi.cast(rffi.LONGP, result)[0])
+ jit_libffi.jit_ffi_call(cif_descr, funcaddr, buf)
+ result = rffi.ptradd(buf, cif_descr.exchange_result)
+ return self.wrap_result(space, rffi.cast(rffi.VOIDPP, result)[0])
class SmartPointerExecutor(InstanceExecutor):
@@ -313,9 +371,14 @@ def get_executor(space, name):
#
# If all fails, a default is used, which can be ignored at least until use.
- name = capi.c_resolve_name(space, name)
+ # original, exact match
+ try:
+ return _executors[name](space, None)
+ except KeyError:
+ pass
- # full, qualified match
+ # resolved, exact match
+ name = capi.c_resolve_name(space, name)
try:
return _executors[name](space, None)
except KeyError:
@@ -355,6 +418,13 @@ def get_executor(space, name):
return SmartPointerPtrExecutor(space, clsdecl, check_smart[1], check_smart[2])
# fall through: can still return smart pointer in non-smart way
+ if clean_name.find('std::complex', 0, 12) == 0 and\
+ (0 < clean_name.find('double') or 0 < clean_name.find('float')):
+ if compound == '':
+ return ComplexExecutor(space, clsdecl)
+ elif compound == '&':
+ return ComplexRefExecutor(space, clsdecl)
+
if compound == '':
return InstanceExecutor(space, clsdecl)
elif compound == '*' or compound == '&':
@@ -376,6 +446,9 @@ def get_executor(space, name):
_executors["void"] = VoidExecutor
_executors["void*"] = PtrTypeExecutor
_executors["const char*"] = CStringExecutor
+_executors["wchar_t"] = WCharExecutor
+_executors["char16_t"] = Char16Executor
+_executors["char32_t"] = Char32Executor
# long double not really supported: narrows to double
_executors["long double"] = LongDoubleExecutor
@@ -384,7 +457,7 @@ _executors["long double&"] = LongDoubleRefExecutor
# special cases (note: 'string' aliases added below)
_executors["constructor"] = ConstructorExecutor
-_executors["std::string"] = StdStringExecutor
+_executors["std::basic_string<char>"] = StdStringExecutor
_executors["const std::basic_string<char>&"] = StdStringRefExecutor
_executors["std::basic_string<char>&"] = StdStringRefExecutor
@@ -394,18 +467,20 @@ _executors["PyObject*"] = PyObjectExecutor
def _build_basic_executors():
"NOT_RPYTHON"
type_info = (
- (bool, capi.c_call_b, ("bool",)),
+ (bool, capi.c_call_b, ("bool",)),
# TODO: either signed or unsigned is correct for a given platform ...
- (rffi.CHAR, capi.c_call_c, ("char", "unsigned char", "signed char")),
- (rffi.SHORT, capi.c_call_h, ("short", "short int", "unsigned short", "unsigned short int")),
- (rffi.INT, capi.c_call_i, ("int", "internal_enum_type_t")),
- (rffi.UINT, capi.c_call_l, ("unsigned", "unsigned int")),
- (rffi.LONG, capi.c_call_l, ("long", "long int")),
- (rffi.ULONG, capi.c_call_l, ("unsigned long", "unsigned long int")),
- (rffi.LONGLONG, capi.c_call_ll, ("long long", "long long int", "Long64_t")),
- (rffi.ULONGLONG, capi.c_call_ll, ("unsigned long long", "unsigned long long int", "ULong64_t")),
- (rffi.FLOAT, capi.c_call_f, ("float",)),
- (rffi.DOUBLE, capi.c_call_d, ("double",)),
+ (rffi.CHAR, capi.c_call_c, ("char", "unsigned char", "signed char")),
+ (ffitypes.INT8_T, capi.c_call_c, ("int8_t",)),
+ (ffitypes.UINT8_T, capi.c_call_c, ("uint8_t", "std::byte", "byte",)),
+ (rffi.SHORT, capi.c_call_h, ("short", "short int", "unsigned short", "unsigned short int")),
+ (rffi.INT, capi.c_call_i, ("int", "internal_enum_type_t")),
+ (rffi.UINT, capi.c_call_l, ("unsigned", "unsigned int")),
+ (rffi.LONG, capi.c_call_l, ("long", "long int")),
+ (rffi.ULONG, capi.c_call_l, ("unsigned long", "unsigned long int")),
+ (rffi.LONGLONG, capi.c_call_ll, ("long long", "long long int", "Long64_t")),
+ (rffi.ULONGLONG, capi.c_call_ll, ("unsigned long long", "unsigned long long int", "ULong64_t")),
+ (rffi.FLOAT, capi.c_call_f, ("float",)),
+ (rffi.DOUBLE, capi.c_call_d, ("double",)),
# (rffi.LONGDOUBLE, capi.c_call_ld, ("long double",)),
)
@@ -453,10 +528,9 @@ def _add_aliased_executors():
aliases = (
("const char*", "char*"),
- ("std::string", "string"),
- ("std::string", "std::basic_string<char>"),
- ("const std::basic_string<char>&", "const string&"),
- ("std::basic_string<char>&", "string&"),
+ ("std::basic_string<char>", "std::string"),
+ ("const std::basic_string<char>&", "const std::string&"),
+ ("std::basic_string<char>&", "std::string&"),
("PyObject*", "_object*"),
)
diff --git a/pypy/module/_cppyy/ffitypes.py b/pypy/module/_cppyy/ffitypes.py
index af2c879bd5..205f99d4cc 100644
--- a/pypy/module/_cppyy/ffitypes.py
+++ b/pypy/module/_cppyy/ffitypes.py
@@ -1,6 +1,8 @@
from pypy.interpreter.error import oefmt
+from pypy.interpreter.unicodehelper import utf8_encode_utf_16, utf8_encode_utf_32
+from pypy.objspace.std.unicodeobject import W_UnicodeObject
-from rpython.rtyper.lltypesystem import rffi
+from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib.rarithmetic import r_singlefloat, r_longfloat
from rpython.rlib.rbigint import rbigint
@@ -14,6 +16,9 @@ class State(object):
def __init__(self, space):
nt = newtype # module from _cffi_backend
+ # the below are (expected to be) lookups, not actual new types, hence
+ # the underlying wrapped primitive class need not be specified
+
# builtin types
self.c_void = nt.new_void_type(space)
self.c_bool = nt.new_primitive_type(space, '_Bool')
@@ -34,12 +39,19 @@ class State(object):
# pointer types
self.c_ccharp = nt.new_pointer_type(space, self.c_char)
self.c_voidp = nt.new_pointer_type(space, self.c_void)
+ self.c_voidpp = nt.new_pointer_type(space, self.c_voidp)
# special types
+ self.c_int8_t = nt.new_primitive_type(space, 'int8_t')
+ self.c_uint8_t = nt.new_primitive_type(space, 'uint8_t')
self.c_size_t = nt.new_primitive_type(space, 'size_t')
self.c_ptrdiff_t = nt.new_primitive_type(space, 'ptrdiff_t')
self.c_intptr_t = nt.new_primitive_type(space, 'intptr_t')
self.c_uintptr_t = nt.new_primitive_type(space, 'uintptr_t')
+ self.c_wchar_t = nt.new_primitive_type(space, 'wchar_t')
+ self.c_char16_t = nt.new_primitive_type(space, 'char16_t')
+ self.c_char32_t = nt.new_primitive_type(space, 'char32_t')
+
class BoolTypeMixin(object):
_mixin_ = True
@@ -70,7 +82,7 @@ class CharTypeMixin(object):
c_ptrtype = rffi.CCHARP # there's no such thing as rffi.CHARP
def _wrap_object(self, space, obj):
- return space.newbytes(obj)
+ return space.newbytes(rffi.cast(self.c_type, obj))
def _unwrap_object(self, space, w_value):
# allow int to pass to char and make sure that str is of length 1
@@ -89,19 +101,29 @@ class CharTypeMixin(object):
raise oefmt(space.w_ValueError,
"char expected, got string of size %d", len(value))
- value = rffi.cast(rffi.CHAR, value[0])
- return value # turn it into a "char" to the annotator
+ value = rffi.cast(rffi.CHAR, value[0])
+ return value
def cffi_type(self, space):
state = space.fromcache(State)
return state.c_char
+class SCharTypeMixin(CharTypeMixin):
+ _mixin_ = True
+ _immutable_fields_ = ['c_type', 'c_ptrtype']
+
+ c_type = rffi.SIGNEDCHAR
+ c_ptrtype = rffi.CCHARP # SIGNEDCHARP is not recognized as a char type for str
+
+ def _wrap_object(self, space, obj):
+ return space.newbytes(rffi.cast(rffi.CHAR, rffi.cast(self.c_type, obj)))
+
class UCharTypeMixin(object):
_mixin_ = True
_immutable_fields_ = ['c_type', 'c_ptrtype']
c_type = rffi.UCHAR
- c_ptrtype = rffi.CCHARP # there's no such thing as rffi.UCHARP
+ c_ptrtype = rffi.CCHARP # UCHARP is not recognized as a char type for str
def _wrap_object(self, space, obj):
return space.newbytes(obj)
@@ -123,22 +145,136 @@ class UCharTypeMixin(object):
raise oefmt(space.w_ValueError,
"unsigned char expected, got string of size %d", len(value))
- value = rffi.cast(rffi.CHAR, value[0])
+ value = rffi.cast(rffi.CHAR, value[0])
return value # turn it into a "char" to the annotator
def cffi_type(self, space):
state = space.fromcache(State)
return state.c_char
+class WCharTypeMixin(object):
+ _mixin_ = True
+ _immutable_fields_ = ['c_type', 'c_ptrtype']
+
+ c_type = lltype.UniChar
+ c_ptrtype = rffi.CWCHARP
+
+ def _wrap_object(self, space, obj):
+ result = rffi.cast(self.c_type, obj)
+ u = rffi.cast(lltype.UniChar, result)
+ return W_UnicodeObject(u.encode('utf8'), 1)
+
+ def _unwrap_object(self, space, w_value):
+ utf8, length = space.utf8_len_w(space.unicode_from_object(w_value))
+ if length != 1:
+ raise oefmt(space.w_ValueError,
+ "wchar_t expected, got string of size %d", length)
+
+ with rffi.scoped_utf82wcharp(utf8, length) as u:
+ value = rffi.cast(self.c_type, u[0])
+ return value
+
+ def cffi_type(self, space):
+ state = space.fromcache(State)
+ return state.c_wchar_t
+
+
+def select_sized_int(size):
+ for t, p in [(rffi.SHORT, rffi.SHORTP), (rffi.INT, rffi.INTP), (rffi.LONG, rffi.LONGP)]:
+ if rffi.sizeof(t) == size:
+ return t, p
+ raise NotImplementedError("no integer type of size %d available" % size)
+
+CHAR16_T = 'char16_t'
+class Char16TypeMixin(object):
+ _mixin_ = True
+ _immutable_fields_ = ['c_type', 'c_ptrtype']
+
+ c_type, c_ptrtype = select_sized_int(2)
+
+ def _wrap_object(self, space, obj):
+ result = rffi.cast(self.c_type, obj)
+ u = rffi.cast(lltype.UniChar, result)
+ return W_UnicodeObject(u.encode('utf8'), 1)
+
+ def _unwrap_object(self, space, w_value):
+ utf8, length = space.utf8_len_w(space.unicode_from_object(w_value))
+ if length != 1:
+ raise oefmt(space.w_ValueError,
+ "char16_t expected, got string of size %d", length)
+
+ utf16 = utf8_encode_utf_16(utf8, 'strict')
+ rawstr = rffi.str2charp(utf16)
+ value = rffi.cast(self.c_ptrtype, lltype.direct_ptradd(rawstr, 2))[0] # adjust BOM
+ lltype.free(rawstr, flavor='raw')
+ return value
+
+ def cffi_type(self, space):
+ state = space.fromcache(State)
+ return state.c_char16_t
+
+CHAR32_T = 'char32_t'
+class Char32TypeMixin(object):
+ _mixin_ = True
+ _immutable_fields_ = ['c_type', 'c_ptrtype']
+
+ c_type, c_ptrtype = select_sized_int(4)
+
+ def _wrap_object(self, space, obj):
+ result = rffi.cast(self.c_type, obj)
+ u = rffi.cast(lltype.UniChar, result)
+ return W_UnicodeObject(u.encode('utf8'), 1)
+
+ def _unwrap_object(self, space, w_value):
+ utf8, length = space.utf8_len_w(space.unicode_from_object(w_value))
+ if length != 1:
+ raise oefmt(space.w_ValueError,
+ "char32_t expected, got string of size %d", length)
+
+ utf32 = utf8_encode_utf_32(utf8, 'strict')
+ rawstr = rffi.str2charp(utf32)
+ value = rffi.cast(self.c_ptrtype, lltype.direct_ptradd(rawstr, 4))[0] # adjust BOM
+ lltype.free(rawstr, flavor='raw')
+ return value
+
+ def cffi_type(self, space):
+ state = space.fromcache(State)
+ return state.c_char32_t
+
+
class BaseIntTypeMixin(object):
_mixin_ = True
def _wrap_object(self, space, obj):
- return space.newint(rffi.cast(rffi.INT, obj))
+ return space.newint(rffi.cast(rffi.INT, rffi.cast(self.c_type, obj)))
def _unwrap_object(self, space, w_obj):
return rffi.cast(self.c_type, space.c_int_w(w_obj))
+INT8_T = 'int8_t'
+class Int8TypeMixin(BaseIntTypeMixin):
+ _mixin_ = True
+ _immutable_fields_ = ['c_type', 'c_ptrtype']
+
+ c_type = rffi.SIGNEDCHAR
+ c_ptrtype = rffi.SIGNEDCHARP
+
+ def cffi_type(self, space):
+ state = space.fromcache(State)
+ return state.c_int8_t
+
+UINT8_T = 'uint8_t'
+class UInt8TypeMixin(BaseIntTypeMixin):
+ _mixin_ = True
+ _immutable_fields_ = ['c_type', 'c_ptrtype']
+
+ c_type = rffi.UCHAR
+ c_ptrtype = rffi.UCHARP
+
+ def cffi_type(self, space):
+ state = space.fromcache(State)
+ return state.c_uint8_t
+
class ShortTypeMixin(BaseIntTypeMixin):
_mixin_ = True
_immutable_fields_ = ['c_type', 'c_ptrtype']
@@ -146,22 +282,22 @@ class ShortTypeMixin(BaseIntTypeMixin):
c_type = rffi.SHORT
c_ptrtype = rffi.SHORTP
-class UShortTypeMixin(BaseIntTypeMixin):
def cffi_type(self, space):
state = space.fromcache(State)
return state.c_short
+class UShortTypeMixin(BaseIntTypeMixin):
_mixin_ = True
_immutable_fields_ = ['c_type', 'c_ptrtype']
c_type = rffi.USHORT
c_ptrtype = rffi.USHORTP
-class IntTypeMixin(BaseIntTypeMixin):
def cffi_type(self, space):
state = space.fromcache(State)
return state.c_ushort
+class IntTypeMixin(BaseIntTypeMixin):
_mixin_ = True
_immutable_fields_ = ['c_type', 'c_ptrtype']
@@ -317,7 +453,13 @@ def typeid(c_type):
"NOT_RPYTHON"
if c_type == bool: return BoolTypeMixin
if c_type == rffi.CHAR: return CharTypeMixin
+ if c_type == rffi.SIGNEDCHAR: return SCharTypeMixin
if c_type == rffi.UCHAR: return UCharTypeMixin
+ if c_type == lltype.UniChar: return WCharTypeMixin # rffi.W_CHAR_T is rffi.INT
+ if c_type == CHAR16_T: return Char16TypeMixin # no type in rffi
+ if c_type == CHAR32_T: return Char32TypeMixin # id.
+ if c_type == INT8_T: return Int8TypeMixin # id.
+ if c_type == UINT8_T: return UInt8TypeMixin # id.
if c_type == rffi.SHORT: return ShortTypeMixin
if c_type == rffi.USHORT: return UShortTypeMixin
if c_type == rffi.INT: return IntTypeMixin
diff --git a/pypy/module/_cppyy/helper.py b/pypy/module/_cppyy/helper.py
index c5a8d5f5a3..826ae66922 100644
--- a/pypy/module/_cppyy/helper.py
+++ b/pypy/module/_cppyy/helper.py
@@ -36,7 +36,7 @@ def _find_qualifier_index(name):
# search from the back; note len(name) > 0 (so rtyper can use uint)
for i in range(len(name) - 1, 0, -1):
c = name[i]
- if c.isalnum() or c == ">" or c == "]":
+ if c.isalnum() or c in ['_', '>', ']', ')']:
break
return i + 1
diff --git a/pypy/module/_cppyy/include/capi.h b/pypy/module/_cppyy/include/capi.h
index a032a064d9..04044dd353 100644
--- a/pypy/module/_cppyy/include/capi.h
+++ b/pypy/module/_cppyy/include/capi.h
@@ -11,6 +11,7 @@ extern "C" {
typedef size_t cppyy_scope_t;
typedef cppyy_scope_t cppyy_type_t;
+ typedef void* cppyy_enum_t;
typedef void* cppyy_object_t;
typedef intptr_t cppyy_method_t;
@@ -20,7 +21,10 @@ extern "C" {
typedef unsigned long cppyy_exctype_t;
/* direct interpreter access ---------------------------------------------- */
+ RPY_EXTERN
int cppyy_compile(const char* code);
+ RPY_EXTERN
+ char* cppyy_to_string(cppyy_type_t klass, cppyy_object_t obj);
/* name to opaque C++ scope representation -------------------------------- */
RPY_EXTERN
@@ -36,6 +40,11 @@ extern "C" {
RPY_EXTERN
size_t cppyy_size_of_type(const char* type_name);
+ RPY_EXTERN
+ int cppyy_is_builtin(const char* type_name);
+ RPY_EXTERN
+ int cppyy_is_complete(const char* type_name);
+
/* memory management ------------------------------------------------------ */
RPY_EXTERN
cppyy_object_t cppyy_allocate(cppyy_type_t type);
@@ -103,11 +112,16 @@ extern "C" {
int cppyy_is_abstract(cppyy_type_t type);
RPY_EXTERN
int cppyy_is_enum(const char* type_name);
+ RPY_EXTERN
+ int cppyy_is_aggregate(cppyy_type_t type);
+ RPY_EXTERN
+ int cppyy_is_default_constructable(cppyy_type_t type);
RPY_EXTERN
const char** cppyy_get_all_cpp_names(cppyy_scope_t scope, size_t* count);
/* namespace reflection information --------------------------------------- */
+ RPY_EXTERN
cppyy_index_t* cppyy_get_using_namespaces(cppyy_scope_t scope);
/* class reflection information ------------------------------------------- */
@@ -132,6 +146,9 @@ extern "C" {
RPY_EXTERN
void cppyy_add_smartptr_type(const char* type_name);
+ RPY_EXTERN
+ void cppyy_add_type_reducer(const char* reducable, const char* reduced);
+
/* calculate offsets between declared and actual type, up-cast: direction > 0; down-cast: direction < 0 */
RPY_EXTERN
ptrdiff_t cppyy_base_offset(cppyy_type_t derived, cppyy_type_t base, cppyy_object_t address, int direction);
@@ -140,6 +157,8 @@ extern "C" {
RPY_EXTERN
int cppyy_num_methods(cppyy_scope_t scope);
RPY_EXTERN
+ int cppyy_num_methods_ns(cppyy_scope_t scope);
+ RPY_EXTERN
cppyy_index_t* cppyy_method_indices_from_name(cppyy_scope_t scope, const char* name);
RPY_EXTERN
@@ -158,7 +177,7 @@ extern "C" {
RPY_EXTERN
int cppyy_method_req_args(cppyy_method_t);
RPY_EXTERN
- char* cppyy_method_arg_name(cppyy_method_t,int arg_index);
+ char* cppyy_method_arg_name(cppyy_method_t, int arg_index);
RPY_EXTERN
char* cppyy_method_arg_type(cppyy_method_t, int arg_index);
RPY_EXTERN
@@ -174,9 +193,13 @@ extern "C" {
RPY_EXTERN
int cppyy_get_num_templated_methods(cppyy_scope_t scope);
+ RPY_EXPORTED
+ int cppyy_get_num_templated_methods_ns(cppyy_scope_t scope);
RPY_EXTERN
char* cppyy_get_templated_method_name(cppyy_scope_t scope, cppyy_index_t imeth);
RPY_EXTERN
+ int cppyy_is_templated_constructor(cppyy_scope_t scope, cppyy_index_t imeth);
+ RPY_EXTERN
int cppyy_exists_method_template(cppyy_scope_t scope, const char* name);
RPY_EXTERN
int cppyy_method_is_template(cppyy_scope_t scope, cppyy_index_t idx);
@@ -191,6 +214,8 @@ extern "C" {
RPY_EXTERN
int cppyy_is_publicmethod(cppyy_method_t);
RPY_EXTERN
+ int cppyy_is_protectedmethod(cppyy_method_t);
+ RPY_EXTERN
int cppyy_is_constructor(cppyy_method_t);
RPY_EXTERN
int cppyy_is_destructor(cppyy_method_t);
@@ -200,6 +225,8 @@ extern "C" {
/* data member reflection information ------------------------------------- */
RPY_EXTERN
int cppyy_num_datamembers(cppyy_scope_t scope);
+ RPY_EXPORTED
+ int cppyy_num_datamembers_ns(cppyy_scope_t scope);
RPY_EXTERN
char* cppyy_datamember_name(cppyy_scope_t scope, int datamember_index);
RPY_EXTERN
@@ -213,6 +240,8 @@ extern "C" {
RPY_EXTERN
int cppyy_is_publicdata(cppyy_type_t type, cppyy_index_t datamember_index);
RPY_EXTERN
+ int cppyy_is_protecteddata(cppyy_type_t type, cppyy_index_t datamember_index);
+ RPY_EXTERN
int cppyy_is_staticdata(cppyy_type_t type, cppyy_index_t datamember_index);
RPY_EXTERN
int cppyy_is_const_data(cppyy_scope_t scope, cppyy_index_t idata);
@@ -221,6 +250,16 @@ extern "C" {
RPY_EXTERN
int cppyy_get_dimension_size(cppyy_scope_t scope, cppyy_index_t idata, int dimension);
+ /* enum properties -------------------------------------------------------- */
+ RPY_EXTERN
+ cppyy_enum_t cppyy_get_enum(cppyy_scope_t scope, const char* enum_name);
+ RPY_EXTERN
+ cppyy_index_t cppyy_get_num_enum_data(cppyy_enum_t);
+ RPY_EXTERN
+ const char* cppyy_get_enum_data_name(cppyy_enum_t, cppyy_index_t idata);
+ RPY_EXTERN
+ long long cppyy_get_enum_data_value(cppyy_enum_t, cppyy_index_t idata);
+
/* misc helpers ----------------------------------------------------------- */
RPY_EXTERN
long long cppyy_strtoll(const char* str);
diff --git a/pypy/module/_cppyy/interp_cppyy.py b/pypy/module/_cppyy/interp_cppyy.py
index b114ee17c0..c0ebaf104c 100644
--- a/pypy/module/_cppyy/interp_cppyy.py
+++ b/pypy/module/_cppyy/interp_cppyy.py
@@ -146,7 +146,7 @@ def register_class(space, w_pycppclass):
# class allows simple aliasing of methods)
capi.pythonize(space, w_pycppclass, cppclass.name)
state = space.fromcache(State)
- state.cppclass_registry[rffi.cast(rffi.LONG, cppclass.handle)] = w_pycppclass
+ state.cppclass_registry[cppclass.handle] = w_pycppclass
class W_CPPLibrary(W_Root):
@@ -169,7 +169,7 @@ W_CPPLibrary.typedef.acceptable_as_base_class = True
#
# W_CPPOverload: instance methods (base class)
# W_CPPConstructorOverload: constructors
-# W_CPPAbstractCtorOverload: to provent instantiation of abstract classes
+# W_CPPAbstractCtorOverload: to prevent instantiation of abstract classes
# W_CPPStaticOverload: free and static functions
# W_CPPTemplateOverload: templated methods
# W_CPPTemplateStaticOverload: templated free and static functions
@@ -270,8 +270,8 @@ class CPPMethod(object):
if cppthis:
# this pointer
data = rffi.ptradd(buffer, cif_descr.exchange_args[0])
- x = rffi.cast(rffi.LONGP, data) # LONGP needed for test_zjit.py
- x[0] = rffi.cast(rffi.LONG, cppthis)
+ x = rffi.cast(rffi.VOIDPP, data)
+ x[0] = rffi.cast(rffi.VOIDP, cppthis)
thisoff = 1
# actual provided arguments
@@ -803,7 +803,7 @@ class TemplateOverloadMixin(object):
elif space.isinstance_w(w_tp, space.w_type):
try:
# cppyy bound types
- s = space.text_w(space.getattr(w_tp, space.newtext('__cppname__')))
+ s = space.text_w(space.getattr(w_tp, space.newtext('__cpp_name__')))
if args_w:
# try to specialize the type match for the given object
cppinstance = self.space.interp_w(W_CPPInstance, args_w[i])
@@ -826,13 +826,14 @@ class TemplateOverloadMixin(object):
tmpl_args += s
return tmpl_args
- def find_method_template(self, name, proto = ''):
- # find/instantiate new callable function
+ def instantiate_method_template(self, name, proto = ''):
+ # instantiate/find new callable function
space = self.space
cppmeth = capi.c_get_method_template(space, self.scope, name, proto)
if not cppmeth:
raise oefmt(self.space.w_AttributeError,
- "scope '%s' has no function %s", self.scope.name, name)
+ "failed to instantiate %s::%s for arguments '%s'",
+ self.scope.name, name, proto)
funcs = []
ftype = self.scope._make_cppfunction(name, cppmeth, funcs)
@@ -842,53 +843,46 @@ class TemplateOverloadMixin(object):
cppol = W_CPPOverload(space, self.scope, funcs[:], self.flags)
return cppol
- def instantiate_and_call(self, name, args_w):
+ def _call_method(self, method, args_w):
+ if not self.space.is_w(self.w_this, self.space.w_None):
+ return self.space.call_obj_args(method, self.w_this, Arguments(self.space, args_w))
+ return self.space.call_args(method, Arguments(self.space, args_w))
+
+ def template_call(self, name, tmpl_args, args_w):
method = None
+
+ fullname = name
+ if tmpl_args is not None:
+ fullname = fullname+'<'+tmpl_args+'>'
+
try:
# existing cached instantiations
- if name[-1] == '>': # only accept full templated name, to ensure explicit
- method = self.master.overloads[name]
- else:
- # try to match with run-time instantiations
- # TODO: logically, this could be used, but in practice, it's proving too
- # greedy ... maybe as a last resort?
- #for cppol in self.master.overloads.values():
- # try:
- # if not self.space.is_w(self.w_this, self.space.w_None):
- # return self.space.call_obj_args(cppol, self.w_this, Arguments(self.space, args_w))
- # return self.space.call_args(cppol, Arguments(self.space, args_w))
- # except Exception:
- # pass # completely ignore for now; have to see whether errors become confusing
- raise TypeError("pre-existing overloads failed")
- except (KeyError, TypeError):
- # if not known, try to deduce from argument types
- w_types = self.space.newtuple([self.space.type(obj_w) for obj_w in args_w])
- proto = self.construct_template_args(w_types, args_w)
- method = self.find_method_template(name, proto)
-
- # only cache result if the name retains the full template
- # TODO: the problem is in part that c_method_full_name returns incorrect names,
- # e.g. when default template arguments are involved, so for now use 'name' if it
- # has the full templated name
- if name[-1] == '>':
- fullname = name
+ method = self.master.overloads[fullname]
+ return self._call_method(method, args_w)
+ except Exception:
+ pass
+
+ # if not known, or failed, try instantiation
+ w_types = self.space.newtuple([self.space.type(obj_w) for obj_w in args_w])
+ proto = self.construct_template_args(w_types, args_w)
+ method = self.instantiate_method_template(fullname, proto) # may raise
+
+ # cache result as the full templated name only
+ if fullname[-1] != '>':
+ fullname = capi.c_method_full_name(self.space, method.functions[0].cppmethod)
+ try:
+ existing = self.master.overloads[fullname]
+ allf = existing.functions + method.functions
+ if isinstance(existing, W_CPPStaticOverload):
+ cppol = W_CPPStaticOverload(self.space, self.scope, allf, self.flags)
else:
- fullname = capi.c_method_full_name(self.space, method.functions[0].cppmethod)
- try:
- existing = self.master.overloads[fullname]
- allf = existing.functions + method.functions
- if isinstance(existing, W_CPPStaticOverload):
- cppol = W_CPPStaticOverload(self.space, self.scope, allf, self.flags)
- else:
- cppol = W_CPPOverload(self.space, self.scope, allf, self.flags)
- self.master.overloads[fullname] = cppol
- except KeyError:
- self.master.overloads[fullname] = method
+ cppol = W_CPPOverload(self.space, self.scope, allf, self.flags)
+ self.master.overloads[fullname] = cppol
+ except KeyError:
+ self.master.overloads[fullname] = method
- if method is not None:
- if not self.space.is_w(self.w_this, self.space.w_None):
- return self.space.call_obj_args(method, self.w_this, Arguments(self.space, args_w))
- return self.space.call_args(method, Arguments(self.space, args_w))
+ # perform actual call (which may still fail)
+ return self._call_method(method, args_w)
def getitem_impl(self, name, args_w):
space = self.space
@@ -899,14 +893,7 @@ class TemplateOverloadMixin(object):
w_args = space.newtuple(args_w)
tmpl_args = self.construct_template_args(w_args)
- fullname = name+'<'+tmpl_args+'>'
- try:
- method = self.master.overloads[fullname]
- except KeyError as e:
- # defer instantiation until arguments are known
- return self.clone(tmpl_args)
-
- return method.descr_get(self.w_this, None)
+ return self.clone(tmpl_args) # defer instantiation until arguments are known
class W_CPPTemplateOverload(W_CPPOverload, TemplateOverloadMixin):
@@ -944,19 +931,11 @@ class W_CPPTemplateOverload(W_CPPOverload, TemplateOverloadMixin):
def call_args(self, args_w):
# direct call: either pick non-templated overload or attempt to deduce
# the template instantiation from the argument types
-
- # do explicit lookup with tmpl_args if given
try:
- fullname = self.name
- if self.tmpl_args is not None:
- fullname = fullname+'<'+self.tmpl_args+'>'
- return self.instantiate_and_call(fullname, args_w)
+ return W_CPPOverload.call_args(self, [self.w_this]+args_w)
except Exception:
pass
-
- # otherwise, try existing overloads or compile-time instantiations
- # TODO: consolidate errors
- return W_CPPOverload.call_args(self, [self.w_this]+args_w)
+ return self.template_call(self.name, self.tmpl_args, args_w)
@unwrap_spec(args_w='args_w')
def getitem(self, args_w):
@@ -1019,20 +998,11 @@ class W_CPPTemplateStaticOverload(W_CPPStaticOverload, TemplateOverloadMixin):
def call_args(self, args_w):
# direct call: either pick non-templated overload or attempt to deduce
# the template instantiation from the argument types
- # TODO: refactor with W_CPPTemplateOverload
-
- # do explicit lookup with tmpl_args if given
try:
- fullname = self.name
- if self.tmpl_args is not None:
- fullname = fullname+'<'+self.tmpl_args+'>'
- return self.instantiate_and_call(fullname, args_w)
+ return W_CPPStaticOverload.call_args(self, [self.w_this]+args_w)
except Exception:
pass
-
- # otherwise, try existing overloads or compile-time instantiations
- # TODO: consolidate errors
- return W_CPPStaticOverload.call_args(self, args_w)
+ return self.template_call(self.name, self.tmpl_args, args_w)
@unwrap_spec(args_w='args_w')
def getitem(self, args_w):
@@ -1081,7 +1051,7 @@ class W_CPPDataMember(W_Root):
self.space = space
self.scope = decl_scope
self.converter = converter.get_converter(self.space, type_name, dimensions)
- self.offset = rffi.cast(rffi.LONG, offset)
+ self.offset = rffi.cast(rffi.INTPTR_T, offset)
def _get_offset(self, cppinstance):
if cppinstance:
@@ -1282,7 +1252,7 @@ class W_CPPNamespaceDecl(W_CPPScopeDecl):
if capi.c_is_enum_data(self.space, self, dm_idx):
type_name = capi.c_resolve_enum(self.space, type_name)
offset = capi.c_datamember_offset(self.space, self, dm_idx)
- if offset == -1:
+ if offset == rffi.cast(rffi.INTPTR_T, -1):
raise self.missing_attribute_error(dm_name)
dims = self._encode_dm_dimensions(dm_idx)
if capi.c_is_const_data(self.space, self, dm_idx):
@@ -1339,7 +1309,7 @@ W_CPPNamespaceDecl.typedef = TypeDef(
get_datamember = interp2app(W_CPPNamespaceDecl.get_datamember),
is_namespace = interp2app(W_CPPNamespaceDecl.is_namespace),
has_enum = interp2app(W_CPPNamespaceDecl.has_enum),
- __cppname__ = interp_attrproperty('name', W_CPPNamespaceDecl, wrapfn="newtext"),
+ __cpp_name__ = interp_attrproperty('name', W_CPPNamespaceDecl, wrapfn="newtext"),
__dispatch__ = interp2app(W_CPPNamespaceDecl.scope__dispatch__),
__dir__ = interp2app(W_CPPNamespaceDecl.ns__dir__),
)
@@ -1395,7 +1365,7 @@ class W_CPPClassDecl(W_CPPScopeDecl):
ftype = ftype_tmp[pyname]
CPPMethodSort(methods).sort()
if ftype & FUNCTION_IS_CONSTRUCTOR:
- if capi.c_is_abstract(self.space, self.handle):
+ if capi.c_is_abstract(self.space, self):
overload = W_CPPAbstractCtorOverload(self.space, self, methods[:])
else:
overload = W_CPPConstructorOverload(self.space, self, methods[:])
@@ -1448,7 +1418,7 @@ class W_CPPClassDecl(W_CPPScopeDecl):
datamember_name = capi.c_datamember_name(self.space, self, i)
type_name = capi.c_datamember_type(self.space, self, i)
offset = capi.c_datamember_offset(self.space, self, i)
- if offset == -1:
+ if offset == rffi.cast(rffi.INTPTR_T, -1):
continue # dictionary problem; raises AttributeError on use
is_static = bool(capi.c_is_staticdata(self.space, self, i))
is_const = bool(capi.c_is_const_data(self.space, self, i))
@@ -1504,7 +1474,7 @@ W_CPPClassDecl.typedef = TypeDef(
get_datamember = interp2app(W_CPPClassDecl.get_datamember),
is_namespace = interp2app(W_CPPClassDecl.is_namespace),
has_enum = interp2app(W_CPPClassDecl.has_enum),
- __cppname__ = interp_attrproperty('name', W_CPPClassDecl, wrapfn="newtext"),
+ __cpp_name__ = interp_attrproperty('name', W_CPPClassDecl, wrapfn="newtext"),
__dispatch__ = interp2app(W_CPPClassDecl.scope__dispatch__)
)
W_CPPClassDecl.typedef.acceptable_as_base_class = False
@@ -1532,7 +1502,7 @@ W_CPPComplexClassDecl.typedef = TypeDef(
get_datamember_names = interp2app(W_CPPComplexClassDecl.get_datamember_names),
get_datamember = interp2app(W_CPPComplexClassDecl.get_datamember),
is_namespace = interp2app(W_CPPComplexClassDecl.is_namespace),
- __cppname__ = interp_attrproperty('name', W_CPPComplexClassDecl, wrapfn="newtext"),
+ __cpp_name__ = interp_attrproperty('name', W_CPPComplexClassDecl, wrapfn="newtext"),
__dispatch__ = interp2app(W_CPPComplexClassDecl.scope__dispatch__)
)
W_CPPComplexClassDecl.typedef.acceptable_as_base_class = False
@@ -1597,7 +1567,7 @@ class W_CPPInstance(W_Root):
return self._rawobject
elif self.smartdecl and self.deref:
args = capi.c_allocate_function_args(self.space, 0)
- rawptr = capi.c_call_l(self.space, self.deref, self._rawobject, 0, args)
+ rawptr = capi.c_call_r(self.space, self.deref, self._rawobject, 0, args)
capi.c_deallocate_function_args(self.space, args)
return rffi.cast(capi.C_OBJECT, rawptr)
else:
@@ -1635,7 +1605,7 @@ class W_CPPInstance(W_Root):
nss = scope_byname(self.space, name)
meth_idx = capi.c_get_global_operator(
self.space, nss, self.clsdecl, other.clsdecl, "operator==")
- if meth_idx != -1:
+ if meth_idx != rffi.cast(capi.C_INDEX, -1):
funcs = []
cppmeth = capi.c_get_method(self.space, nss, meth_idx)
nss._make_cppfunction("operator==", cppmeth, funcs)
@@ -1688,7 +1658,7 @@ class W_CPPInstance(W_Root):
if w_as_builtin is not None:
return self.space.repr(w_as_builtin)
return self.space.newtext("<%s object at 0x%x>" %
- (self.clsdecl.name, rffi.cast(rffi.ULONG, self.get_rawobject())))
+ (self.clsdecl.name, rffi.cast(rffi.UINTPTR_T, self.get_rawobject())))
def smartptr(self):
if self._rawobject and self.smartdecl:
@@ -1736,7 +1706,7 @@ class MemoryRegulator:
def register(obj):
if not obj._rawobject:
return
- addr_as_int = int(rffi.cast(rffi.LONG, obj.get_rawobject()))
+ addr_as_int = int(rffi.cast(rffi.INTPTR_T, obj.get_rawobject()))
clsdecl = obj.clsdecl
assert isinstance(clsdecl, W_CPPClassDecl)
clsdecl.cppobjects.set(addr_as_int, obj)
@@ -1745,7 +1715,7 @@ class MemoryRegulator:
def unregister(obj):
if not obj._rawobject:
return
- addr_as_int = int(rffi.cast(rffi.LONG, obj.get_rawobject()))
+ addr_as_int = int(rffi.cast(rffi.INTPTR_T, obj.get_rawobject()))
clsdecl = obj.clsdecl
assert isinstance(clsdecl, W_CPPClassDecl)
clsdecl.cppobjects.set(addr_as_int, None) # actually deletes (pops)
@@ -1754,7 +1724,7 @@ class MemoryRegulator:
def retrieve(clsdecl, address):
if not address:
return None
- addr_as_int = int(rffi.cast(rffi.LONG, address))
+ addr_as_int = int(rffi.cast(rffi.INTPTR_T, address))
assert isinstance(clsdecl, W_CPPClassDecl)
return clsdecl.cppobjects.get(addr_as_int)
@@ -1764,7 +1734,7 @@ memory_regulator = MemoryRegulator()
def get_pythonized_cppclass(space, handle):
state = space.fromcache(State)
try:
- w_pycppclass = state.cppclass_registry[rffi.cast(rffi.LONG, handle)]
+ w_pycppclass = state.cppclass_registry[handle]
except KeyError:
final_name = capi.c_scoped_final_name(space, handle)
# the callback will cache the class by calling register_class
diff --git a/pypy/module/_cppyy/pythonify.py b/pypy/module/_cppyy/pythonify.py
index e6210c7e50..47ccd689d9 100644
--- a/pypy/module/_cppyy/pythonify.py
+++ b/pypy/module/_cppyy/pythonify.py
@@ -83,7 +83,7 @@ def with_metaclass(meta, *bases):
# C++ namespace base class (the C++ class base class defined in _post_import_startup)
class CPPNamespace(with_metaclass(CPPNamespaceMeta, object)):
def __init__(self):
- raise TypeError("cannot instantiate namespace '%s'", self.__cppname__)
+ raise TypeError("cannot instantiate namespace '%s'", self.__cpp_name__)
# TODO: this can be moved to the interp level (and share template argument
@@ -100,8 +100,8 @@ class CPPTemplate(object):
# arguments are strings representing types, types, or builtins
if type(arg) == str:
return arg # string describing type
- elif hasattr(arg, '__cppname__'):
- return arg.__cppname__ # C++ bound type
+ elif hasattr(arg, '__cpp_name__'):
+ return arg.__cpp_name__ # C++ bound type
elif arg == str:
import _cppyy
return _cppyy._std_string_name() # special case pystr -> C++ string
@@ -187,9 +187,9 @@ def make_cppnamespace(scope, name, decl):
ns_meta = type(CPPNamespace)(name+'_meta', (CPPNamespaceMeta,), {})
# create the python-side C++ namespace representation, cache in scope if given
- d = {"__cppdecl__" : decl,
- "__module__" : make_module_name(scope),
- "__cppname__" : decl.__cppname__ }
+ d = {"__cppdecl__" : decl,
+ "__module__" : make_module_name(scope),
+ "__cpp_name__" : decl.__cpp_name__ }
pyns = ns_meta(name, (CPPNamespace,), d)
if scope:
setattr(scope, name, pyns)
@@ -242,11 +242,10 @@ def make_cppclass(scope, cl_name, decl):
cppol = decl.__dispatch__(m_name, signature)
return MethodType(cppol, self, type(self))
d_class = {"__cppdecl__" : decl,
- "__new__" : make_new(decl),
- "__module__" : make_module_name(scope),
- "__cppname__" : decl.__cppname__,
- "__dispatch__" : dispatch,
- }
+ "__new__" : make_new(decl),
+ "__module__" : make_module_name(scope),
+ "__cpp_name__" : decl.__cpp_name__,
+ "__dispatch__" : dispatch,}
# insert (static) methods into the class dictionary
for m_name in decl.get_method_names():
@@ -275,7 +274,7 @@ def make_cppclass(scope, cl_name, decl):
# needs to run first, so that the generic pythonizations can use them
import _cppyy
_cppyy._register_class(pycls)
- _pythonize(pycls, pycls.__cppname__)
+ _pythonize(pycls, pycls.__cpp_name__)
return pycls
def make_cpptemplatetype(scope, template_name):
@@ -287,7 +286,7 @@ def get_scoped_pycppitem(scope, name, type_only=False):
# resolve typedefs/aliases: these may cross namespaces, in which case
# the lookup must trigger the creation of all necessary scopes
- scoped_name = (scope == gbl) and name or (scope.__cppname__+'::'+name)
+ scoped_name = (scope == gbl) and name or (scope.__cpp_name__+'::'+name)
final_scoped_name = _cppyy._resolve_name(scoped_name)
if final_scoped_name != scoped_name:
pycppitem = get_pycppitem(final_scoped_name)
@@ -434,11 +433,13 @@ def _pythonize(pyclass, name):
return self
pyclass.__iadd__ = iadd
+ is_vector = name.find('std::vector', 0, 11) == 0
+
# map begin()/end() protocol to iter protocol on STL(-like) classes, but
# not on vector, which is pythonized in the capi (interp-level; there is
# also the fallback on the indexed __getitem__, but that is slower)
add_checked_item = False
- if name.find('std::vector', 0, 11) != 0:
+ if not is_vector:
if 'begin' in pyclass.__dict__ and 'end' in pyclass.__dict__:
if _cppyy._scope_byname(name+'::iterator') or \
_cppyy._scope_byname(name+'::const_iterator'):
@@ -458,7 +459,7 @@ def _pythonize(pyclass, name):
add_checked_item = True
# add python collection based initializer
- if name.find('std::vector', 0, 11) == 0:
+ else:
pyclass.__real_init__ = pyclass.__init__
def vector_init(self, *args):
if len(args) == 1 and isinstance(args[0], (tuple, list)):
@@ -482,7 +483,7 @@ def _pythonize(pyclass, name):
# TODO: must be a simpler way to check (or at least hook these to a namespace
# std specific pythonizor)
- if add_checked_item or name.find('std::vector', 0, 11) == 0 or \
+ if add_checked_item or is_vector or \
name.find('std::array', 0, 11) == 0 or name.find('std::deque', 0, 10) == 0:
# combine __getitem__ and __len__ to make a pythonized __getitem__
if '__getitem__' in pyclass.__dict__ and '__len__' in pyclass.__dict__:
@@ -503,7 +504,7 @@ def _pythonize(pyclass, name):
pyclass.__str__ = pyclass.c_str
# std::pair unpacking through iteration
- if 'std::pair' == name[:9]:
+ elif name.find('std::pair', 0, 9) == 0:
def getitem(self, idx):
if idx == 0: return self.first
if idx == 1: return self.second
@@ -513,6 +514,30 @@ def _pythonize(pyclass, name):
pyclass.__getitem__ = getitem
pyclass.__len__ = return2
+ # std::complex integration with Python complex
+ elif name.find('std::complex', 0, 12) == 0:
+ def getreal(obj):
+ return obj.__cpp_real()
+ def setreal(obj, val):
+ obj.__cpp_real(val)
+ pyclass.__cpp_real = pyclass.real
+ pyclass.real = property(getreal, setreal)
+
+ def getimag(obj):
+ return obj.__cpp_imag()
+ def setimag(obj, val):
+ obj.__cpp_imag(val)
+ pyclass.__cpp_imag = pyclass.imag
+ pyclass.imag = property(getimag, setimag)
+
+ def cmplx(self):
+ return self.real+self.imag*1.j
+ pyclass.__complex__ = cmplx
+
+ def cmplx_repr(self):
+ return repr(self.__complex__())
+ pyclass.__repr__ = cmplx_repr
+
# user provided, custom pythonizations
try:
ns_name, cl_name = extract_namespace(name)
diff --git a/pypy/module/_cppyy/src/dummy_backend.cxx b/pypy/module/_cppyy/src/dummy_backend.cxx
index 55d49b3af3..a4663cbf8d 100644
--- a/pypy/module/_cppyy/src/dummy_backend.cxx
+++ b/pypy/module/_cppyy/src/dummy_backend.cxx
@@ -1,15 +1,23 @@
#include "capi.h"
+// include all headers from datatype.cxx and example01.cxx here,
+// allowing those .cxx files to be placed in the "dummy" namespace
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <cwchar>
+
+#include <complex>
+#include <functional>
#include <map>
+#include <memory>
#include <string>
#include <sstream>
#include <utility>
#include <vector>
-#include <assert.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
+#include <sys/types.h>
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
@@ -47,6 +55,22 @@ struct CPPYY_G__value {
int type;
};
+
+// gInterpreter
+namespace dummy {
+ class TInterpreter {
+ public:
+ int ProcessLine(const char* line) {
+ if (strcmp(line, "__cplusplus;") == 0)
+ return 0;
+ return -1;
+ }
+ };
+
+ TInterpreter gInterpreter;
+} // namespace dummy
+
+
// add example01.cxx code
int globalAddOneToInt(int a);
@@ -172,17 +196,38 @@ int Pseudo_kLots = 42;
struct Cppyy_InitPseudoReflectionInfo {
Cppyy_InitPseudoReflectionInfo() {
- // class example01 --
static cppyy_scope_t s_scope_id = 0;
{ // namespace ''
s_handles[""] = (cppyy_scope_t)++s_scope_id;
+
+ std::vector<Cppyy_PseudoDatambrInfo> data;
+ data.push_back(Cppyy_PseudoDatambrInfo("N", "int", (ptrdiff_t)&dummy::N, true));
+ data.push_back(Cppyy_PseudoDatambrInfo(
+ "gInterpreter", "TInterpreter", (ptrdiff_t)&dummy::gInterpreter, true));
+
+ Cppyy_PseudoClassInfo info(std::vector<Cppyy_PseudoMethodInfo*>(), data);
+ s_scopes[(cppyy_scope_t)s_scope_id] = info;
}
{ // namespace std
s_handles["std"] = (cppyy_scope_t)++s_scope_id;
}
+ { // class TInterpreter
+ s_handles["TInterpreter"] = (cppyy_scope_t)++s_scope_id;
+
+ std::vector<Cppyy_PseudoMethodInfo*> methods;
+
+ std::vector<std::string> argtypes;
+ argtypes.push_back("const char*");
+ methods.push_back(new Cppyy_PseudoMethodInfo("ProcessLine", argtypes, "int"));
+ s_methods["TInterpreter::ProcessLine_cchar*"] = methods.back();
+
+ Cppyy_PseudoClassInfo info(methods, std::vector<Cppyy_PseudoDatambrInfo>());
+ s_scopes[(cppyy_scope_t)s_scope_id] = info;
+ }
+
{ // class example01 --
s_handles["example01"] = (cppyy_scope_t)++s_scope_id;
@@ -308,6 +353,64 @@ struct Cppyy_InitPseudoReflectionInfo {
//====================================================================
+ { // class complex<double> --
+ s_handles["complex_t"] = (cppyy_scope_t)++s_scope_id;
+ s_handles["std::complex<double>"] = s_handles["complex_t"];
+
+ std::vector<Cppyy_PseudoMethodInfo*> methods;
+
+ std::vector<std::string> argtypes;
+
+ // double real()
+ argtypes.clear();
+ methods.push_back(new Cppyy_PseudoMethodInfo("real", argtypes, "double"));
+ s_methods["std::complex<double>::real"] = methods.back();
+
+ // double imag()
+ argtypes.clear();
+ methods.push_back(new Cppyy_PseudoMethodInfo("imag", argtypes, "double"));
+ s_methods["std::complex<double>::imag"] = methods.back();
+
+ // complex<double>(double r, double i)
+ argtypes.clear();
+ argtypes.push_back("double");
+ argtypes.push_back("double");
+ methods.push_back(new Cppyy_PseudoMethodInfo("complex<double>", argtypes, "constructor", kConstructor));
+ s_methods["std::complex<double>::complex<double>_double_double"] = methods.back();
+
+ Cppyy_PseudoClassInfo info(methods, std::vector<Cppyy_PseudoDatambrInfo>());
+ s_scopes[(cppyy_scope_t)s_scope_id] = info;
+ }
+
+ { // class complex<int> --
+ s_handles["icomplex_t"] = (cppyy_scope_t)++s_scope_id;
+ s_handles["std::complex<int>"] = s_handles["icomplex_t"];
+
+ std::vector<Cppyy_PseudoMethodInfo*> methods;
+
+ std::vector<std::string> argtypes;
+
+ // int real()
+ argtypes.clear();
+ methods.push_back(new Cppyy_PseudoMethodInfo("real", argtypes, "int"));
+ s_methods["std::complex<int>::real"] = methods.back();
+
+ // int imag()
+ argtypes.clear();
+ methods.push_back(new Cppyy_PseudoMethodInfo("imag", argtypes, "int"));
+ s_methods["std::complex<int>::imag"] = methods.back();
+
+ // complex<int>(int r, int i)
+ argtypes.clear();
+ argtypes.push_back("int");
+ argtypes.push_back("int");
+ methods.push_back(new Cppyy_PseudoMethodInfo("complex<int>", argtypes, "constructor", kConstructor));
+ s_methods["std::complex<int>::complex<int>_int_int"] = methods.back();
+
+ Cppyy_PseudoClassInfo info(methods, std::vector<Cppyy_PseudoDatambrInfo>());
+ s_scopes[(cppyy_scope_t)s_scope_id] = info;
+ }
+
{ // class payload --
s_handles["payload"] = (cppyy_scope_t)++s_scope_id;
@@ -350,30 +453,42 @@ struct Cppyy_InitPseudoReflectionInfo {
s_methods["CppyyTestData::destroy_arrays"] = methods.back();
std::vector<Cppyy_PseudoDatambrInfo> data;
- PUBLIC_CPPYY_DATA2(bool, bool);
- PUBLIC_CPPYY_DATA (char, char);
- PUBLIC_CPPYY_DATA (schar, signed char);
- PUBLIC_CPPYY_DATA2(uchar, unsigned char);
- 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);
- PUBLIC_CPPYY_DATA (llong, long long);
- PUBLIC_CPPYY_DATA (ullong, unsigned long long);
- PUBLIC_CPPYY_DATA (long64, Long64_t);
- PUBLIC_CPPYY_DATA (ulong64, ULong64_t);
- PUBLIC_CPPYY_DATA3(float, float, f);
- PUBLIC_CPPYY_DATA3(double, double, d);
- PUBLIC_CPPYY_DATA (ldouble, long double);
- PUBLIC_CPPYY_DATA (enum, CppyyTestData::EWhat);
- PUBLIC_CPPYY_DATA (voidp, void*);
+ PUBLIC_CPPYY_DATA2(bool, bool);
+ PUBLIC_CPPYY_DATA (char, char);
+ PUBLIC_CPPYY_DATA2(schar, signed char);
+ PUBLIC_CPPYY_DATA2(uchar, unsigned char);
+ PUBLIC_CPPYY_DATA (wchar, wchar_t);
+ PUBLIC_CPPYY_DATA (char16, char16_t);
+ PUBLIC_CPPYY_DATA (char32, char32_t);
+ PUBLIC_CPPYY_DATA (int8, int8_t);
+ PUBLIC_CPPYY_DATA (uint8, uint8_t);
+ 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);
+ PUBLIC_CPPYY_DATA (llong, long long);
+ PUBLIC_CPPYY_DATA (ullong, unsigned long long);
+ PUBLIC_CPPYY_DATA (long64, Long64_t);
+ PUBLIC_CPPYY_DATA (ulong64, ULong64_t);
+ PUBLIC_CPPYY_DATA3(float, float, f);
+ PUBLIC_CPPYY_DATA3(double, double, d);
+ PUBLIC_CPPYY_DATA (ldouble, long double);
+ PUBLIC_CPPYY_DATA (complex, complex_t);
+ PUBLIC_CPPYY_DATA (icomplex, icomplex_t);
+ PUBLIC_CPPYY_DATA (enum, CppyyTestData::EWhat);
+ PUBLIC_CPPYY_DATA (voidp, void*);
PUBLIC_CPPYY_STATIC_DATA(char, char);
PUBLIC_CPPYY_STATIC_DATA(schar, signed char);
PUBLIC_CPPYY_STATIC_DATA(uchar, unsigned char);
+ PUBLIC_CPPYY_STATIC_DATA(wchar, wchar_t);
+ PUBLIC_CPPYY_STATIC_DATA(char16, char16_t);
+ PUBLIC_CPPYY_STATIC_DATA(char32, char32_t);
+ PUBLIC_CPPYY_STATIC_DATA(int8, int8_t);
+ PUBLIC_CPPYY_STATIC_DATA(uint8, uint8_t);
PUBLIC_CPPYY_STATIC_DATA(short, short);
PUBLIC_CPPYY_STATIC_DATA(ushort, unsigned short);
PUBLIC_CPPYY_STATIC_DATA(int, int);
@@ -435,7 +550,11 @@ static INLINE char* cppstring_to_cstring(const std::string& name) {
/* name to opaque C++ scope representation -------------------------------- */
char* cppyy_resolve_name(const char* cppitem_name) {
- if (cppyy_is_enum(cppitem_name))
+ if (strcmp(cppitem_name, "complex_t") == 0)
+ return cppstring_to_cstring("std::complex<double>");
+ else if (strcmp(cppitem_name, "icomplex_t") == 0)
+ return cppstring_to_cstring("std::complex<int>");
+ else if (cppyy_is_enum(cppitem_name))
return cppstring_to_cstring("internal_enum_type_t");
else if (strcmp(cppitem_name, "aap_t") == 0)
return cppstring_to_cstring("long double");
@@ -483,6 +602,27 @@ void cppyy_call_v(cppyy_method_t method, cppyy_object_t self, int nargs, void* a
} else if (idx == s_methods["CppyyTestData::set_uchar"]) {
assert(self && nargs == 1);
((dummy::CppyyTestData*)self)->set_uchar(((CPPYY_G__value*)args)[0].obj.uch);
+ } else if (idx == s_methods["CppyyTestData::set_wchar"]) {
+ assert(self && nargs == 1);
+ ((dummy::CppyyTestData*)self)->set_wchar(((CPPYY_G__value*)args)[0].obj.i);
+ } else if (idx == s_methods["CppyyTestData::set_char16"]) {
+ assert(self && nargs == 1);
+ ((dummy::CppyyTestData*)self)->set_char16(((CPPYY_G__value*)args)[0].obj.i);
+ } else if (idx == s_methods["CppyyTestData::set_char32"]) {
+ assert(self && nargs == 1);
+ ((dummy::CppyyTestData*)self)->set_char32(((CPPYY_G__value*)args)[0].obj.i);
+ } else if (idx == s_methods["CppyyTestData::set_int8"]) {
+ assert(self && nargs == 1);
+ ((dummy::CppyyTestData*)self)->set_int8(((CPPYY_G__value*)args)[0].obj.ch);
+ } else if (idx == s_methods["CppyyTestData::set_int8_cr"]) {
+ assert(self && nargs == 1);
+ ((dummy::CppyyTestData*)self)->set_int8_cr(*(int8_t*)&((CPPYY_G__value*)args)[0]);
+ } else if (idx == s_methods["CppyyTestData::set_uint8"]) {
+ assert(self && nargs == 1);
+ ((dummy::CppyyTestData*)self)->set_uint8(((CPPYY_G__value*)args)[0].obj.ch);
+ } else if (idx == s_methods["CppyyTestData::set_uint8_cr"]) {
+ assert(self && nargs == 1);
+ ((dummy::CppyyTestData*)self)->set_uint8_cr(*(uint8_t*)&((CPPYY_G__value*)args)[0]);
} else if (idx == s_methods["CppyyTestData::set_short"]) {
assert(self && nargs == 1);
((dummy::CppyyTestData*)self)->set_short(((CPPYY_G__value*)args)[0].obj.sh);
@@ -575,6 +715,12 @@ char cppyy_call_c(cppyy_method_t method, cppyy_object_t self, int nargs, void* a
} else if (idx == s_methods["CppyyTestData::get_uchar"]) {
assert(self && nargs == 0);
result = (char)((dummy::CppyyTestData*)self)->get_uchar();
+ } else if (idx == s_methods["CppyyTestData::get_int8"]) {
+ assert(self && nargs == 0);
+ result = (long)((dummy::CppyyTestData*)self)->get_int8();
+ } else if (idx == s_methods["CppyyTestData::get_uint8"]) {
+ assert(self && nargs == 0);
+ result = (long)((dummy::CppyyTestData*)self)->get_uint8();
} else {
assert(!"method unknown in cppyy_call_c");
}
@@ -599,7 +745,11 @@ short cppyy_call_h(cppyy_method_t method, cppyy_object_t self, int nargs, void*
int cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
int result = 0;
Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
- if (idx == s_methods["static_example01::staticAddOneToInt_int"]) {
+ if (idx == s_methods["TInterpreter::ProcessLine_cchar*"]) {
+ assert(self && nargs == 1);
+ result = ((dummy::TInterpreter*)self)->ProcessLine(
+ (const char*)(*(intptr_t*)&((CPPYY_G__value*)args)[0]));
+ } else if (idx == s_methods["static_example01::staticAddOneToInt_int"]) {
assert(!self && nargs == 1);
result = dummy::example01::staticAddOneToInt(((CPPYY_G__value*)args)[0].obj.in);
} else if (idx == s_methods["static_example01::staticAddOneToInt_int_int"]) {
@@ -622,6 +772,12 @@ int cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, void* ar
} else if (idx == s_methods["CppyyTestData::get_int"]) {
assert(self && nargs == 0);
result = ((dummy::CppyyTestData*)self)->get_int();
+ } else if (idx == s_methods["std::complex<int>::real"]) {
+ assert(self && nargs == 0);
+ result = ((std::complex<int>*)self)->real();
+ } else if (idx == s_methods["std::complex<int>::imag"]) {
+ assert(self && nargs == 0);
+ result = ((std::complex<int>*)self)->imag();
} else {
assert(!"method unknown in cppyy_call_i");
}
@@ -631,23 +787,15 @@ int cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, void* ar
long cppyy_call_l(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
long result = 0;
Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
- if (idx == s_methods["static_example01::staticStrcpy_cchar*"]) {
- assert(!self && nargs == 1);
- result = (long)dummy::example01::staticStrcpy(
- (const char*)(*(intptr_t*)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["static_example01::staticCyclePayload_payload*_double"]) {
- assert(!self && nargs == 2);
- result = (long)dummy::example01::staticCyclePayload(
- (dummy::payload*)(*(intptr_t*)&((CPPYY_G__value*)args)[0]),
- ((CPPYY_G__value*)args)[1].obj.d);
- } else if (idx == s_methods["example01::addToStringValue_cchar*"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::example01*)self)->addToStringValue(
- (const char*)(*(intptr_t*)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["example01::cyclePayload_payload*"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::example01*)self)->cyclePayload(
- (dummy::payload*)(*(intptr_t*)&((CPPYY_G__value*)args)[0]));
+ if (idx == s_methods["CppyyTestData::get_wchar"]) {
+ assert(self && nargs == 0);
+ result = (long)((dummy::CppyyTestData*)self)->get_wchar();
+ } else if (idx == s_methods["CppyyTestData::get_char16"]) {
+ assert(self && nargs == 0);
+ result = (long)((dummy::CppyyTestData*)self)->get_char16();
+ } else if (idx == s_methods["CppyyTestData::get_char32"]) {
+ assert(self && nargs == 0);
+ result = (long)((dummy::CppyyTestData*)self)->get_char32();
} else if (idx == s_methods["CppyyTestData::get_uint"]) {
assert(self && nargs == 0);
result = (long)((dummy::CppyyTestData*)self)->get_uint();
@@ -657,118 +805,6 @@ long cppyy_call_l(cppyy_method_t method, cppyy_object_t self, int nargs, void* a
} else if (idx == s_methods["CppyyTestData::get_ulong"]) {
assert(self && nargs == 0);
result = (long)((dummy::CppyyTestData*)self)->get_ulong();
- } else if (idx == s_methods["CppyyTestData::get_bool_array"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_bool_array();
- } else if (idx == s_methods["CppyyTestData::get_bool_array2"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_bool_array2();
- } else if (idx == s_methods["CppyyTestData::get_uchar_array"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_uchar_array();
- } else if (idx == s_methods["CppyyTestData::get_uchar_array2"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_uchar_array2();
- } else if (idx == s_methods["CppyyTestData::get_short_array"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_short_array();
- } else if (idx == s_methods["CppyyTestData::get_short_array2"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_short_array2();
- } else if (idx == s_methods["CppyyTestData::get_ushort_array"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_ushort_array();
- } else if (idx == s_methods["CppyyTestData::get_ushort_array2"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_ushort_array2();
- } else if (idx == s_methods["CppyyTestData::get_int_array"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_int_array();
- } else if (idx == s_methods["CppyyTestData::get_int_array2"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_int_array2();
- } else if (idx == s_methods["CppyyTestData::get_uint_array"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_uint_array();
- } else if (idx == s_methods["CppyyTestData::get_uint_array2"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_uint_array2();
- } else if (idx == s_methods["CppyyTestData::get_long_array"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_long_array();
- } else if (idx == s_methods["CppyyTestData::get_long_array2"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_long_array2();
- } else if (idx == s_methods["CppyyTestData::get_ulong_array"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_ulong_array();
- } else if (idx == s_methods["CppyyTestData::get_ulong_array2"]) {
- assert(self && nargs == 0);
- result = (long)((dummy::CppyyTestData*)self)->get_ulong_array2();
- } else if (idx == s_methods["CppyyTestData::pass_array_short"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_array(
- (*(short**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_void_array_h"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_void_array_h(
- (*(short**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_array_ushort"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_array(
- (*(unsigned short**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_void_array_H"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_void_array_H(
- (*(unsigned short**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_array_int"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_array(
- (*(int**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_void_array_i"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_void_array_i(
- (*(int**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_array_uint"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_array(
- (*(unsigned int**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_void_array_I"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_void_array_I(
- (*(unsigned int**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_array_long"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_array(
- (*(long**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_void_array_l"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_void_array_l(
- (*(intptr_t**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_array_ulong"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_array(
- (*(unsigned long**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_void_array_L"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_void_array_L(
- (*(uintptr_t**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_array_float"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_array(
- (*(float**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_void_array_f"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_void_array_f(
- (*(float**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_array_double"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_array(
- (*(double**)&((CPPYY_G__value*)args)[0]));
- } else if (idx == s_methods["CppyyTestData::pass_void_array_d"]) {
- assert(self && nargs == 1);
- result = (long)((dummy::CppyyTestData*)self)->pass_void_array_d(
- (*(double**)&((CPPYY_G__value*)args)[0]));
} else {
assert(!"method unknown in cppyy_call_l");
}
@@ -817,6 +853,12 @@ double cppyy_call_d(cppyy_method_t method, cppyy_object_t self, int nargs, void*
} else if (idx == s_methods["CppyyTestData::get_double"]) {
assert(self && nargs == 0);
result = ((dummy::CppyyTestData*)self)->get_double();
+ } else if (idx == s_methods["std::complex<double>::real"]) {
+ assert(self && nargs == 0);
+ result = ((std::complex<double>*)self)->real();
+ } else if (idx == s_methods["std::complex<double>::imag"]) {
+ assert(self && nargs == 0);
+ result = ((std::complex<double>*)self)->imag();
} else {
assert(!"method unknown in cppyy_call_d");
}
@@ -844,7 +886,7 @@ double cppyy_call_nld(cppyy_method_t method, cppyy_object_t self, int nargs, voi
}
#define DISPATCH_CALL_R_GET(tpname) \
- else if (idx == s_methods["CppyyTestData::get_"#tpname"_r"]) { \
+ else if (idx == s_methods["CppyyTestData::get_"#tpname"_r"]) { \
assert(self && nargs == 0); \
result = (void*)&((dummy::CppyyTestData*)self)->get_##tpname##_r(); \
} else if (idx == s_methods["CppyyTestData::get_"#tpname"_cr"]) { \
@@ -852,24 +894,68 @@ double cppyy_call_nld(cppyy_method_t method, cppyy_object_t self, int nargs, voi
result = (void*)&((dummy::CppyyTestData*)self)->get_##tpname##_cr(); \
}
+#define DISPATCH_CALL_R_GET2(tpname) \
+ DISPATCH_CALL_R_GET(tpname) \
+ else if (idx == s_methods["CppyyTestData::get_"#tpname"_array"]) { \
+ assert(self && nargs == 0); \
+ result = (void*)((dummy::CppyyTestData*)self)->get_##tpname##_array();\
+ } else if (idx == s_methods["CppyyTestData::get_"#tpname"_array2"]) { \
+ assert(self && nargs == 0); \
+ result = (void*)((dummy::CppyyTestData*)self)->get_##tpname##_array2();\
+ }
+
+#define DISPATCH_CALL_R_GET3(tpname, tpcode, type) \
+ DISPATCH_CALL_R_GET2(tpname) \
+ else if (idx == s_methods["CppyyTestData::pass_array_"#tpname]) { \
+ assert(self && nargs == 1); \
+ result = (void*)((dummy::CppyyTestData*)self)->pass_array( \
+ (*(type**)&((CPPYY_G__value*)args)[0])); \
+ } else if (idx == s_methods["CppyyTestData::pass_void_array_"#tpcode]) { \
+ assert(self && nargs == 1); \
+ result = (void*)((dummy::CppyyTestData*)self)->pass_void_array_##tpcode (\
+ (*(type**)&((CPPYY_G__value*)args)[0])); \
+ }
+
void* cppyy_call_r(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
void* result = nullptr;
Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
- if (0) {}
- DISPATCH_CALL_R_GET(bool)
- DISPATCH_CALL_R_GET(short)
- DISPATCH_CALL_R_GET(ushort)
- DISPATCH_CALL_R_GET(int)
- DISPATCH_CALL_R_GET(uint)
- DISPATCH_CALL_R_GET(long)
- DISPATCH_CALL_R_GET(ulong)
- DISPATCH_CALL_R_GET(llong)
- DISPATCH_CALL_R_GET(ullong)
- DISPATCH_CALL_R_GET(long64)
- DISPATCH_CALL_R_GET(ulong64)
- DISPATCH_CALL_R_GET(float)
- DISPATCH_CALL_R_GET(double)
- DISPATCH_CALL_R_GET(ldouble)
+ if (idx == s_methods["static_example01::staticStrcpy_cchar*"]) {
+ assert(!self && nargs == 1);
+ result = (void*)dummy::example01::staticStrcpy(
+ (const char*)(*(intptr_t*)&((CPPYY_G__value*)args)[0]));
+ } else if (idx == s_methods["static_example01::staticCyclePayload_payload*_double"]) {
+ assert(!self && nargs == 2);
+ result = (void*)dummy::example01::staticCyclePayload(
+ (dummy::payload*)(*(intptr_t*)&((CPPYY_G__value*)args)[0]),
+ ((CPPYY_G__value*)args)[1].obj.d);
+ } else if (idx == s_methods["example01::addToStringValue_cchar*"]) {
+ assert(self && nargs == 1);
+ result = (void*)((dummy::example01*)self)->addToStringValue(
+ (const char*)(*(intptr_t*)&((CPPYY_G__value*)args)[0]));
+ } else if (idx == s_methods["example01::cyclePayload_payload*"]) {
+ assert(self && nargs == 1);
+ result = (void*)((dummy::example01*)self)->cyclePayload(
+ (dummy::payload*)(*(intptr_t*)&((CPPYY_G__value*)args)[0]));
+ }
+ DISPATCH_CALL_R_GET2(bool)
+ DISPATCH_CALL_R_GET (wchar)
+ DISPATCH_CALL_R_GET (int8)
+ DISPATCH_CALL_R_GET (uint8)
+ DISPATCH_CALL_R_GET3(short, h, short)
+ DISPATCH_CALL_R_GET3(ushort, H, unsigned short)
+ DISPATCH_CALL_R_GET3(int, i, int)
+ DISPATCH_CALL_R_GET3(uint, I, unsigned int)
+ DISPATCH_CALL_R_GET3(long, l, long)
+ DISPATCH_CALL_R_GET3(ulong, L, unsigned long)
+ DISPATCH_CALL_R_GET (llong)
+ DISPATCH_CALL_R_GET (ullong)
+ DISPATCH_CALL_R_GET (long64)
+ DISPATCH_CALL_R_GET (ulong64)
+ DISPATCH_CALL_R_GET3(float, f, float)
+ DISPATCH_CALL_R_GET3(double, d, double)
+ DISPATCH_CALL_R_GET (ldouble)
+ DISPATCH_CALL_R_GET (complex)
+ DISPATCH_CALL_R_GET (icomplex)
else {
assert(!"method unknown in cppyy_call_r");
}
@@ -904,12 +990,32 @@ cppyy_object_t cppyy_constructor(cppyy_method_t method, cppyy_type_t handle, int
} else if (idx == s_methods["CppyyTestData::CppyyTestData"]) {
assert(nargs == 0);
result = new dummy::CppyyTestData;
+ } else if (idx == s_methods["std::complex<double>::complex<double>_double_double"]) {
+ assert(nargs == 2);
+ result = new std::complex<double>(((CPPYY_G__value*)args)[0].obj.d, ((CPPYY_G__value*)args)[1].obj.d);
+ } else if (idx == s_methods["std::complex<int>::complex<int>_int_int"]) {
+ assert(nargs == 2);
+ result = new std::complex<int>(((CPPYY_G__value*)args)[0].obj.i, ((CPPYY_G__value*)args)[1].obj.i);
} else {
assert(!"method unknown in cppyy_constructor");
}
return (cppyy_object_t)result;
}
+cppyy_object_t cppyy_call_o(
+ cppyy_method_t method, cppyy_object_t self, int nargs, void* args, cppyy_type_t result_type) {
+ void* result = 0;
+ Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
+ if (idx == s_methods["CppyyTestData::get_complex"]) {
+ assert(self && nargs == 0);
+ result = new std::complex<double>(((dummy::CppyyTestData*)self)->get_complex());
+ } else if (idx == s_methods["CppyyTestData::get_icomplex"]) {
+ assert(self && nargs == 0);
+ result = new std::complex<int>(((dummy::CppyyTestData*)self)->get_icomplex());
+ }
+ return (cppyy_object_t)result;
+}
+
cppyy_funcaddr_t cppyy_function_address(cppyy_method_t /* method */) {
return (cppyy_funcaddr_t)0;
}
@@ -940,12 +1046,16 @@ size_t cppyy_function_arg_typeoffset() {
/* scope reflection information ------------------------------------------- */
int cppyy_is_namespace(cppyy_scope_t handle) {
- if (handle == s_handles["pyzables"])
+ if (handle == s_handles[std::string("")] ||
+ handle == s_handles["std"] ||
+ handle == s_handles["pyzables"])
return 1;
return 0;
}
-int cppyy_is_template(const char* /* template_name */) {
+int cppyy_is_template(const char* template_name) {
+ if (strcmp(template_name, "std::complex") == 0)
+ return 1;
return 0;
}
@@ -970,7 +1080,12 @@ char* cppyy_final_name(cppyy_type_t handle) {
}
char* cppyy_scoped_final_name(cppyy_type_t handle) {
- return cppyy_final_name(handle);
+ const std::string& rec_name = cppyy_final_name(handle);
+ if (rec_name == "complex_t")
+ return cppstring_to_cstring("std::complex<double>");
+ else if (rec_name == "icomplex_t")
+ return cppstring_to_cstring("std::complex<int>");
+ return cppstring_to_cstring(rec_name);
}
int cppyy_has_complex_hierarchy(cppyy_type_t /* handle */) {
@@ -1029,7 +1144,16 @@ char* cppyy_method_arg_default(cppyy_method_t method, int idx) {
return cppstring_to_cstring("");
}
-char* cppyy_method_signature(cppyy_method_t, int /* show_formalargs */) {
+char* cppyy_method_signature(cppyy_method_t method, int /* show_formalargs */) {
+ Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
+ if (idx == s_methods["std::complex<double>::real"])
+ return cppstring_to_cstring("()");
+ else if (idx == s_methods["std::complex<double>::imag"])
+ return cppstring_to_cstring("()");
+ else if (idx == s_methods["std::complex<int>::real"])
+ return cppstring_to_cstring("()");
+ else if (idx == s_methods["std::complex<int>::imag"])
+ return cppstring_to_cstring("()");
return cppstring_to_cstring("");
}
@@ -1081,6 +1205,8 @@ int cppyy_is_staticmethod(cppyy_method_t method) {
/* data member reflection information ------------------------------------- */
int cppyy_num_datamembers(cppyy_scope_t handle) {
+ if (cppyy_is_namespace(handle))
+ return 0;
return s_scopes[handle].m_datambrs.size();
}
@@ -1096,6 +1222,15 @@ ptrdiff_t cppyy_datamember_offset(cppyy_scope_t handle, int idatambr) {
return s_scopes[handle].m_datambrs[idatambr].m_offset;
}
+int cppyy_datamember_index(cppyy_scope_t handle, const char* name) {
+ if (handle == s_handles[std::string("")]) {
+ if (strcmp(name, "N") == 0) return 0;
+ if (strcmp(name, "gInterpreter") == 0) return 1;
+ }
+
+ return (int)-1;
+}
+
/* data member properties ------------------------------------------------ */
int cppyy_is_publicdata(cppyy_scope_t /* handle */, cppyy_index_t /* idatambr */) {
diff --git a/pypy/module/_cppyy/test/Makefile b/pypy/module/_cppyy/test/Makefile
index cdf513b271..2535696b12 100644
--- a/pypy/module/_cppyy/test/Makefile
+++ b/pypy/module/_cppyy/test/Makefile
@@ -13,9 +13,14 @@ dicts = advancedcppDict.so \
all : $(dicts)
-HASGENREFLEX:=$(shell command -v genreflex 2> /dev/null)
+cppflags=-O3 -fPIC -rdynamic
+
+HASCLINGCONFIG:=$(shell command -v cling-config 2> /dev/null)
+ifdef HASCLINGCONFIG
+ cppflags+=$(shell cling-config --cppflags)
+endif
-cppflags=$(shell cling-config --cppflags) -O3 -fPIC -rdynamic
+HASGENREFLEX:=$(shell command -v genreflex 2> /dev/null)
ifdef HASGENREFLEX
genreflex_flags:=$(shell genreflex --cppflags)
cppflags+=$(genreflex_flags)
@@ -25,7 +30,7 @@ endif
PLATFORM := $(shell uname -s)
ifeq ($(PLATFORM),Darwin)
- cppflags+=-dynamiclib -single_module -undefined dynamic_lookup
+ cppflags+=-dynamiclib -single_module -arch x86_64 -undefined dynamic_lookup -Wno-delete-non-virtual-dtor
endif
diff --git a/pypy/module/_cppyy/test/datatypes.cxx b/pypy/module/_cppyy/test/datatypes.cxx
index 9d6143c7c5..aebfc7c8b6 100644
--- a/pypy/module/_cppyy/test/datatypes.cxx
+++ b/pypy/module/_cppyy/test/datatypes.cxx
@@ -8,60 +8,80 @@ std::vector<EFruit> vecFruits{kCitrus, kApple};
//===========================================================================
CppyyTestData::CppyyTestData() : m_const_int(17), m_owns_arrays(false)
{
- m_bool = false;
- m_char = 'a';
- m_schar = 'b';
- m_uchar = 'c';
- m_short = -11;
- m_ushort = 11u;
- m_int = -22;
- m_uint = 22u;
- m_long = -33l;
- m_ulong = 33ul;
- m_llong = -44ll;
- m_ullong = 44ull;
- m_long64 = -55ll;
- m_ulong64 = 55ull;
- m_float = -66.f;
- m_double = -77.;
- m_ldouble = -88.l;
- m_enum = kNothing;
- m_voidp = (void*)0;
-
- m_bool_array2 = new bool[N];
- m_uchar_array2 = new unsigned char[N];
- m_short_array2 = new short[N];
- m_ushort_array2 = new unsigned short[N];
- m_int_array2 = new int[N];
- m_uint_array2 = new unsigned int[N];
- m_long_array2 = new long[N];
- m_ulong_array2 = new unsigned long[N];
-
- m_float_array2 = new float[N];
- m_double_array2 = new double[N];
+ m_bool = false;
+ m_char = 'a';
+ m_schar = 'b';
+ m_uchar = 'c';
+ m_wchar = L'D';
+ m_char16 = u'\u00df';
+ m_char32 = U'\u00df';
+#if __cplusplus > 201402L
+ m_byte = (std::byte)'d';
+#endif
+ m_int8 = -9;
+ m_uint8 = 9;
+ m_short = -11;
+ m_ushort = 11u;
+ m_int = -22;
+ m_uint = 22u;
+ m_long = -33l;
+ m_ulong = 33ul;
+ m_llong = -44ll;
+ m_ullong = 44ull;
+ m_long64 = -55ll;
+ m_ulong64 = 55ull;
+ m_float = -66.f;
+ m_double = -77.;
+ m_ldouble = -88.l;
+ m_complex = {99., 101.};
+ m_icomplex = {121, 141};
+ m_enum = kNothing;
+ m_voidp = (void*)0;
+
+ m_bool_array2 = new bool[N];
+ m_schar_array2 = new signed char[N];
+ m_uchar_array2 = new unsigned char[N];
+#if __cplusplus > 201402L
+ m_byte_array2 = new std::byte[N];
+#endif
+ m_short_array2 = new short[N];
+ m_ushort_array2 = new unsigned short[N];
+ m_int_array2 = new int[N];
+ m_uint_array2 = new unsigned int[N];
+ m_long_array2 = new long[N];
+ m_ulong_array2 = new unsigned long[N];
+
+ m_float_array2 = new float[N];
+ m_double_array2 = new double[N];
+ m_complex_array2 = new complex_t[N];
for (int i = 0; i < N; ++i) {
- m_bool_array[i] = bool(i%2);
- m_bool_array2[i] = bool((i+1)%2);
- m_uchar_array[i] = 1u*i;
- m_uchar_array2[i] = 2u*i;
- m_short_array[i] = -1*i;
- m_short_array2[i] = -2*i;
- m_ushort_array[i] = 3u*i;
- m_ushort_array2[i] = 4u*i;
- m_int_array[i] = -5*i;
- m_int_array2[i] = -6*i;
- m_uint_array[i] = 7u*i;
- m_uint_array2[i] = 8u*i;
- m_long_array[i] = -9l*i;
- m_long_array2[i] = -10l*i;
- m_ulong_array[i] = 11ul*i;
- m_ulong_array2[i] = 12ul*i;
-
- m_float_array[i] = -13.f*i;
- m_float_array2[i] = -14.f*i;
- m_double_array[i] = -15.*i;
- m_double_array2[i] = -16.*i;
+ m_bool_array[i] = bool(i%2);
+ m_bool_array2[i] = bool((i+1)%2);
+ m_uchar_array[i] = 1u*i;
+ m_uchar_array2[i] = 2u*i;
+#if __cplusplus > 201402L
+ m_byte_array[i] = (std::byte)(3u*i);
+ m_byte_array2[i] = (std::byte)(4u*i);
+#endif
+ m_short_array[i] = -1*i;
+ m_short_array2[i] = -2*i;
+ m_ushort_array[i] = 3u*i;
+ m_ushort_array2[i] = 4u*i;
+ m_int_array[i] = -5*i;
+ m_int_array2[i] = -6*i;
+ m_uint_array[i] = 7u*i;
+ m_uint_array2[i] = 8u*i;
+ m_long_array[i] = -9l*i;
+ m_long_array2[i] = -10l*i;
+ m_ulong_array[i] = 11ul*i;
+ m_ulong_array2[i] = 12ul*i;
+
+ m_float_array[i] = -13.f*i;
+ m_float_array2[i] = -14.f*i;
+ m_double_array[i] = -15.*i;
+ m_double_array2[i] = -16.*i;
+ m_complex_array2[i] = {17.*i, 18.*i};
}
m_owns_arrays = true;
@@ -81,6 +101,9 @@ void CppyyTestData::destroy_arrays() {
if (m_owns_arrays == true) {
delete[] m_bool_array2;
delete[] m_uchar_array2;
+#if __cplusplus > 201402L
+ delete[] m_byte_array2;
+#endif
delete[] m_short_array2;
delete[] m_ushort_array2;
delete[] m_int_array2;
@@ -90,37 +113,54 @@ void CppyyTestData::destroy_arrays() {
delete[] m_float_array2;
delete[] m_double_array2;
+ delete[] m_complex_array2;
m_owns_arrays = false;
}
}
//- getters -----------------------------------------------------------------
-bool CppyyTestData::get_bool() { return m_bool; }
-char CppyyTestData::get_char() { return m_char; }
-signed char CppyyTestData::get_schar() { return m_schar; }
-unsigned char CppyyTestData::get_uchar() { return m_uchar; }
-short CppyyTestData::get_short() { return m_short; }
-unsigned short CppyyTestData::get_ushort() { return m_ushort; }
-int CppyyTestData::get_int() { return m_int; }
-unsigned int CppyyTestData::get_uint() { return m_uint; }
-long CppyyTestData::get_long() { return m_long; }
-unsigned long CppyyTestData::get_ulong() { return m_ulong; }
-long long CppyyTestData::get_llong() { return m_llong; }
-unsigned long long CppyyTestData::get_ullong() { return m_ullong; }
-Long64_t CppyyTestData::get_long64() { return m_long64; }
-ULong64_t CppyyTestData::get_ulong64() { return m_ulong64; }
-float CppyyTestData::get_float() { return m_float; }
-double CppyyTestData::get_double() { return m_double; }
-long double CppyyTestData::get_ldouble() { return m_ldouble; }
+bool CppyyTestData::get_bool() { return m_bool; }
+char CppyyTestData::get_char() { return m_char; }
+signed char CppyyTestData::get_schar() { return m_schar; }
+unsigned char CppyyTestData::get_uchar() { return m_uchar; }
+wchar_t CppyyTestData::get_wchar() { return m_wchar; }
+char16_t CppyyTestData::get_char16() { return m_char16; }
+char32_t CppyyTestData::get_char32() { return m_char32; }
+#if __cplusplus > 201402L
+std::byte CppyyTestData::get_byte() { return m_byte; }
+#endif
+int8_t CppyyTestData::get_int8() { return m_int8; }
+uint8_t CppyyTestData::get_uint8() { return m_uint8; }
+short CppyyTestData::get_short() { return m_short; }
+unsigned short CppyyTestData::get_ushort() { return m_ushort; }
+int CppyyTestData::get_int() { return m_int; }
+unsigned int CppyyTestData::get_uint() { return m_uint; }
+long CppyyTestData::get_long() { return m_long; }
+unsigned long CppyyTestData::get_ulong() { return m_ulong; }
+long long CppyyTestData::get_llong() { return m_llong; }
+unsigned long long CppyyTestData::get_ullong() { return m_ullong; }
+Long64_t CppyyTestData::get_long64() { return m_long64; }
+ULong64_t CppyyTestData::get_ulong64() { return m_ulong64; }
+float CppyyTestData::get_float() { return m_float; }
+double CppyyTestData::get_double() { return m_double; }
+long double CppyyTestData::get_ldouble() { return m_ldouble; }
long double CppyyTestData::get_ldouble_def(long double ld) { return ld; }
-CppyyTestData::EWhat CppyyTestData::get_enum() { return m_enum; }
-void* CppyyTestData::get_voidp() { return m_voidp; }
+complex_t CppyyTestData::get_complex() { return m_complex; }
+icomplex_t CppyyTestData::get_icomplex() { return m_icomplex; }
+CppyyTestData::EWhat CppyyTestData::get_enum() { return m_enum; }
+void* CppyyTestData::get_voidp() { return m_voidp; }
bool* CppyyTestData::get_bool_array() { return m_bool_array; }
bool* CppyyTestData::get_bool_array2() { return m_bool_array2; }
+signed char* CppyyTestData::get_schar_array() { return m_schar_array; }
+signed char* CppyyTestData::get_schar_array2() { return m_schar_array2; }
unsigned char* CppyyTestData::get_uchar_array() { return m_uchar_array; }
unsigned char* CppyyTestData::get_uchar_array2() { return m_uchar_array2; }
+#if __cplusplus > 201402L
+std::byte* CppyyTestData::get_byte_array() { return m_byte_array; }
+std::byte* CppyyTestData::get_byte_array2() { return m_byte_array2; }
+#endif
short* CppyyTestData::get_short_array() { return m_short_array; }
short* CppyyTestData::get_short_array2() { return m_short_array2; }
unsigned short* CppyyTestData::get_ushort_array() { return m_ushort_array; }
@@ -134,10 +174,12 @@ long* CppyyTestData::get_long_array2() { return m_long_array2; }
unsigned long* CppyyTestData::get_ulong_array() { return m_ulong_array; }
unsigned long* CppyyTestData::get_ulong_array2() { return m_ulong_array2; }
-float* CppyyTestData::get_float_array() { return m_float_array; }
-float* CppyyTestData::get_float_array2() { return m_float_array2; }
-double* CppyyTestData::get_double_array() { return m_double_array; }
-double* CppyyTestData::get_double_array2() { return m_double_array2; }
+float* CppyyTestData::get_float_array() { return m_float_array; }
+float* CppyyTestData::get_float_array2() { return m_float_array2; }
+double* CppyyTestData::get_double_array() { return m_double_array; }
+double* CppyyTestData::get_double_array2() { return m_double_array2; }
+complex_t* CppyyTestData::get_complex_array() { return m_complex_array; }
+complex_t* CppyyTestData::get_complex_array2() { return m_complex_array2; }
CppyyTestPod CppyyTestData::get_pod_val() { return m_pod; }
CppyyTestPod* CppyyTestData::get_pod_val_ptr() { return &m_pod; }
@@ -147,65 +189,95 @@ CppyyTestPod*& CppyyTestData::get_pod_ptrref() { return m_ppod; }
CppyyTestPod* CppyyTestData::get_pod_ptr() { return m_ppod; }
//- getters const-ref -------------------------------------------------------
-const bool& CppyyTestData::get_bool_cr() { return m_bool; }
-const char& CppyyTestData::get_char_cr() { return m_char; }
-const signed char& CppyyTestData::get_schar_cr() { return m_schar; }
-const unsigned char& CppyyTestData::get_uchar_cr() { return m_uchar; }
-const short& CppyyTestData::get_short_cr() { return m_short; }
-const unsigned short& CppyyTestData::get_ushort_cr() { return m_ushort; }
-const int& CppyyTestData::get_int_cr() { return m_int; }
-const unsigned int& CppyyTestData::get_uint_cr() { return m_uint; }
-const long& CppyyTestData::get_long_cr() { return m_long; }
-const unsigned long& CppyyTestData::get_ulong_cr() { return m_ulong; }
-const long long& CppyyTestData::get_llong_cr() { return m_llong; }
-const unsigned long long& CppyyTestData::get_ullong_cr() { return m_ullong; }
-const Long64_t& CppyyTestData::get_long64_cr() { return m_long64; }
-const ULong64_t& CppyyTestData::get_ulong64_cr() { return m_ulong64; }
-const float& CppyyTestData::get_float_cr() { return m_float; }
-const double& CppyyTestData::get_double_cr() { return m_double; }
-const long double& CppyyTestData::get_ldouble_cr() { return m_ldouble; }
-const CppyyTestData::EWhat& CppyyTestData::get_enum_cr() { return m_enum; }
+const bool& CppyyTestData::get_bool_cr() { return m_bool; }
+const char& CppyyTestData::get_char_cr() { return m_char; }
+const signed char& CppyyTestData::get_schar_cr() { return m_schar; }
+const unsigned char& CppyyTestData::get_uchar_cr() { return m_uchar; }
+const wchar_t& CppyyTestData::get_wchar_cr() { return m_wchar; }
+const char16_t& CppyyTestData::get_char16_cr() { return m_char16; }
+const char32_t& CppyyTestData::get_char32_cr() { return m_char32; }
+#if __cplusplus > 201402L
+const std::byte& CppyyTestData::get_byte_cr() { return m_byte; }
+#endif
+const int8_t& CppyyTestData::get_int8_cr() { return m_int8; }
+const uint8_t& CppyyTestData::get_uint8_cr() { return m_uint8; }
+const short& CppyyTestData::get_short_cr() { return m_short; }
+const unsigned short& CppyyTestData::get_ushort_cr() { return m_ushort; }
+const int& CppyyTestData::get_int_cr() { return m_int; }
+const unsigned int& CppyyTestData::get_uint_cr() { return m_uint; }
+const long& CppyyTestData::get_long_cr() { return m_long; }
+const unsigned long& CppyyTestData::get_ulong_cr() { return m_ulong; }
+const long long& CppyyTestData::get_llong_cr() { return m_llong; }
+const unsigned long long& CppyyTestData::get_ullong_cr() { return m_ullong; }
+const Long64_t& CppyyTestData::get_long64_cr() { return m_long64; }
+const ULong64_t& CppyyTestData::get_ulong64_cr() { return m_ulong64; }
+const float& CppyyTestData::get_float_cr() { return m_float; }
+const double& CppyyTestData::get_double_cr() { return m_double; }
+const long double& CppyyTestData::get_ldouble_cr() { return m_ldouble; }
+const complex_t& CppyyTestData::get_complex_cr() { return m_complex; }
+const icomplex_t& CppyyTestData::get_icomplex_cr() { return m_icomplex; }
+const CppyyTestData::EWhat& CppyyTestData::get_enum_cr() { return m_enum; }
//- getters ref -------------------------------------------------------------
-bool& CppyyTestData::get_bool_r() { return m_bool; }
-char& CppyyTestData::get_char_r() { return m_char; }
-signed char& CppyyTestData::get_schar_r() { return m_schar; }
-unsigned char& CppyyTestData::get_uchar_r() { return m_uchar; }
-short& CppyyTestData::get_short_r() { return m_short; }
-unsigned short& CppyyTestData::get_ushort_r() { return m_ushort; }
-int& CppyyTestData::get_int_r() { return m_int; }
-unsigned int& CppyyTestData::get_uint_r() { return m_uint; }
-long& CppyyTestData::get_long_r() { return m_long; }
-unsigned long& CppyyTestData::get_ulong_r() { return m_ulong; }
-long long& CppyyTestData::get_llong_r() { return m_llong; }
-unsigned long long& CppyyTestData::get_ullong_r() { return m_ullong; }
-Long64_t& CppyyTestData::get_long64_r() { return m_long64; }
-ULong64_t& CppyyTestData::get_ulong64_r() { return m_ulong64; }
-float& CppyyTestData::get_float_r() { return m_float; }
-double& CppyyTestData::get_double_r() { return m_double; }
-long double& CppyyTestData::get_ldouble_r() { return m_ldouble; }
-CppyyTestData::EWhat& CppyyTestData::get_enum_r() { return m_enum; }
+bool& CppyyTestData::get_bool_r() { return m_bool; }
+char& CppyyTestData::get_char_r() { return m_char; }
+signed char& CppyyTestData::get_schar_r() { return m_schar; }
+unsigned char& CppyyTestData::get_uchar_r() { return m_uchar; }
+wchar_t& CppyyTestData::get_wchar_r() { return m_wchar; }
+char16_t& CppyyTestData::get_char16_r() { return m_char16; }
+char32_t& CppyyTestData::get_char32_r() { return m_char32; }
+#if __cplusplus > 201402L
+std::byte& CppyyTestData::get_byte_r() { return m_byte; }
+#endif
+int8_t& CppyyTestData::get_int8_r() { return m_int8; }
+uint8_t& CppyyTestData::get_uint8_r() { return m_uint8; }
+short& CppyyTestData::get_short_r() { return m_short; }
+unsigned short& CppyyTestData::get_ushort_r() { return m_ushort; }
+int& CppyyTestData::get_int_r() { return m_int; }
+unsigned int& CppyyTestData::get_uint_r() { return m_uint; }
+long& CppyyTestData::get_long_r() { return m_long; }
+unsigned long& CppyyTestData::get_ulong_r() { return m_ulong; }
+long long& CppyyTestData::get_llong_r() { return m_llong; }
+unsigned long long& CppyyTestData::get_ullong_r() { return m_ullong; }
+Long64_t& CppyyTestData::get_long64_r() { return m_long64; }
+ULong64_t& CppyyTestData::get_ulong64_r() { return m_ulong64; }
+float& CppyyTestData::get_float_r() { return m_float; }
+double& CppyyTestData::get_double_r() { return m_double; }
+long double& CppyyTestData::get_ldouble_r() { return m_ldouble; }
+complex_t& CppyyTestData::get_complex_r() { return m_complex; }
+icomplex_t& CppyyTestData::get_icomplex_r() { return m_icomplex; }
+CppyyTestData::EWhat& CppyyTestData::get_enum_r() { return m_enum; }
//- setters -----------------------------------------------------------------
-void CppyyTestData::set_bool(bool b) { m_bool = b; }
-void CppyyTestData::set_char(char c) { m_char = c; }
-void CppyyTestData::set_schar(signed char sc) { m_schar = sc; }
-void CppyyTestData::set_uchar(unsigned char uc) { m_uchar = uc; }
-void CppyyTestData::set_short(short s) { m_short = s; }
-void CppyyTestData::set_ushort(unsigned short us) { m_ushort = us; }
-void CppyyTestData::set_int(int i) { m_int = i; }
-void CppyyTestData::set_uint(unsigned int ui) { m_uint = ui; }
-void CppyyTestData::set_long(long l) { m_long = l; }
-void CppyyTestData::set_ulong(unsigned long ul) { m_ulong = ul; }
-void CppyyTestData::set_llong(long long ll) { m_llong = ll; }
-void CppyyTestData::set_ullong(unsigned long long ull) { m_ullong = ull; }
-void CppyyTestData::set_long64(Long64_t l64) { m_long64 = l64; }
-void CppyyTestData::set_ulong64(ULong64_t ul64) { m_ulong64 = ul64; }
-void CppyyTestData::set_float(float f) { m_float = f; }
-void CppyyTestData::set_double(double d) { m_double = d; }
-void CppyyTestData::set_ldouble(long double ld) { m_ldouble = ld; }
-void CppyyTestData::set_enum(EWhat w) { m_enum = w; }
-void CppyyTestData::set_voidp(void* p) { m_voidp = p; }
+void CppyyTestData::set_bool(bool b) { m_bool = b; }
+void CppyyTestData::set_char(char c) { m_char = c; }
+void CppyyTestData::set_schar(signed char sc) { m_schar = sc; }
+void CppyyTestData::set_uchar(unsigned char uc) { m_uchar = uc; }
+void CppyyTestData::set_wchar(wchar_t wc) { m_wchar = wc; }
+void CppyyTestData::set_char16(char16_t c16) { m_char16 = c16; }
+void CppyyTestData::set_char32(char32_t c32) { m_char32 = c32; }
+#if __cplusplus > 201402L
+void CppyyTestData::set_byte(std::byte b) { m_byte = b; }
+#endif
+void CppyyTestData::set_int8(int8_t s8) { m_int8 = s8; }
+void CppyyTestData::set_uint8(uint8_t u8) { m_uint8 = u8; }
+void CppyyTestData::set_short(short s) { m_short = s; }
+void CppyyTestData::set_ushort(unsigned short us) { m_ushort = us; }
+void CppyyTestData::set_int(int i) { m_int = i; }
+void CppyyTestData::set_uint(unsigned int ui) { m_uint = ui; }
+void CppyyTestData::set_long(long l) { m_long = l; }
+void CppyyTestData::set_ulong(unsigned long ul) { m_ulong = ul; }
+void CppyyTestData::set_llong(long long ll) { m_llong = ll; }
+void CppyyTestData::set_ullong(unsigned long long ull) { m_ullong = ull; }
+void CppyyTestData::set_long64(Long64_t l64) { m_long64 = l64; }
+void CppyyTestData::set_ulong64(ULong64_t ul64) { m_ulong64 = ul64; }
+void CppyyTestData::set_float(float f) { m_float = f; }
+void CppyyTestData::set_double(double d) { m_double = d; }
+void CppyyTestData::set_ldouble(long double ld) { m_ldouble = ld; }
+void CppyyTestData::set_complex(complex_t cd) { m_complex = cd; }
+void CppyyTestData::set_icomplex(icomplex_t ci) { m_icomplex = ci; }
+void CppyyTestData::set_enum(EWhat w) { m_enum = w; }
+void CppyyTestData::set_voidp(void* p) { m_voidp = p; }
void CppyyTestData::set_pod_val(CppyyTestPod p) { m_pod = p; }
void CppyyTestData::set_pod_ptr_in(CppyyTestPod* pp) { m_pod = *pp; }
@@ -220,24 +292,233 @@ void CppyyTestData::set_pod_void_ptrptr_out(void** pp) { delete *((CppyyTe
void CppyyTestData::set_pod_ptr(CppyyTestPod* pp) { m_ppod = pp; }
//- setters const-ref -------------------------------------------------------
-void CppyyTestData::set_bool_cr(const bool& b) { m_bool = b; }
-void CppyyTestData::set_char_cr(const char& c) { m_char = c; }
-void CppyyTestData::set_schar_cr(const signed char& sc) { m_schar = sc; }
-void CppyyTestData::set_uchar_cr(const unsigned char& uc) { m_uchar = uc; }
-void CppyyTestData::set_short_cr(const short& s) { m_short = s; }
-void CppyyTestData::set_ushort_cr(const unsigned short& us) { m_ushort = us; }
-void CppyyTestData::set_int_cr(const int& i) { m_int = i; }
-void CppyyTestData::set_uint_cr(const unsigned int& ui) { m_uint = ui; }
-void CppyyTestData::set_long_cr(const long& l) { m_long = l; }
-void CppyyTestData::set_ulong_cr(const unsigned long& ul) { m_ulong = ul; }
-void CppyyTestData::set_llong_cr(const long long& ll) { m_llong = ll; }
-void CppyyTestData::set_ullong_cr(const unsigned long long& ull) { m_ullong = ull; }
-void CppyyTestData::set_long64_cr(const Long64_t& l64) { m_long64 = l64; }
-void CppyyTestData::set_ulong64_cr(const ULong64_t& ul64) { m_ulong64 = ul64; }
-void CppyyTestData::set_float_cr(const float& f) { m_float = f; }
-void CppyyTestData::set_double_cr(const double& d) { m_double = d; }
-void CppyyTestData::set_ldouble_cr(const long double& ld) { m_ldouble = ld; }
-void CppyyTestData::set_enum_cr(const EWhat& w) { m_enum = w; }
+void CppyyTestData::set_bool_cr(const bool& b) { m_bool = b; }
+void CppyyTestData::set_char_cr(const char& c) { m_char = c; }
+void CppyyTestData::set_schar_cr(const signed char& sc) { m_schar = sc; }
+void CppyyTestData::set_uchar_cr(const unsigned char& uc) { m_uchar = uc; }
+void CppyyTestData::set_wchar_cr(const wchar_t& wc) { m_wchar = wc; }
+void CppyyTestData::set_char16_cr(const char16_t& c16) { m_char16 = c16; }
+void CppyyTestData::set_char32_cr(const char32_t& c32) { m_char32 = c32; }
+#if __cplusplus > 201402L
+void CppyyTestData::set_byte_cr(const std::byte& b) { m_byte = b; }
+#endif
+void CppyyTestData::set_int8_cr(const int8_t& s8) { m_int8 = s8; }
+void CppyyTestData::set_uint8_cr(const uint8_t& u8) { m_uint8 = u8; }
+void CppyyTestData::set_short_cr(const short& s) { m_short = s; }
+void CppyyTestData::set_ushort_cr(const unsigned short& us) { m_ushort = us; }
+void CppyyTestData::set_int_cr(const int& i) { m_int = i; }
+void CppyyTestData::set_uint_cr(const unsigned int& ui) { m_uint = ui; }
+void CppyyTestData::set_long_cr(const long& l) { m_long = l; }
+void CppyyTestData::set_ulong_cr(const unsigned long& ul) { m_ulong = ul; }
+void CppyyTestData::set_llong_cr(const long long& ll) { m_llong = ll; }
+void CppyyTestData::set_ullong_cr(const unsigned long long& ull) { m_ullong = ull; }
+void CppyyTestData::set_long64_cr(const Long64_t& l64) { m_long64 = l64; }
+void CppyyTestData::set_ulong64_cr(const ULong64_t& ul64) { m_ulong64 = ul64; }
+void CppyyTestData::set_float_cr(const float& f) { m_float = f; }
+void CppyyTestData::set_double_cr(const double& d) { m_double = d; }
+void CppyyTestData::set_ldouble_cr(const long double& ld) { m_ldouble = ld; }
+void CppyyTestData::set_complex_cr(const complex_t& cd) { m_complex = cd; }
+void CppyyTestData::set_icomplex_cr(const icomplex_t& ci) { m_icomplex = ci; }
+void CppyyTestData::set_enum_cr(const EWhat& w) { m_enum = w; }
+
+//- setters ref -------------------------------------------------------------
+void CppyyTestData::set_bool_r(bool& b) { b = true; }
+void CppyyTestData::set_char_r(char& c) { c = 'a'; }
+void CppyyTestData::set_wchar_r(wchar_t& wc) { wc = 'b'; }
+void CppyyTestData::set_char16_r(char16_t& c16) { c16 = u'\u6c24'; }
+void CppyyTestData::set_char32_r(char32_t& c32) { c32 = U'\U0001f34e'; }
+void CppyyTestData::set_schar_r(signed char& sc) { sc = 'c'; }
+void CppyyTestData::set_uchar_r(unsigned char& uc) { uc = 'd'; }
+#if __cplusplus > 201402L
+void CppyyTestData::set_byte_r(std::byte& b) { b = (std::byte)'e'; }
+#endif
+void CppyyTestData::set_short_r(short& s) { s = -1; }
+void CppyyTestData::set_ushort_r(unsigned short& us) { us = 2; }
+void CppyyTestData::set_int_r(int& i) { i = -3; }
+void CppyyTestData::set_uint_r(unsigned int& ui) { ui = 4; }
+void CppyyTestData::set_long_r(long& l) { l = -5; }
+void CppyyTestData::set_ulong_r(unsigned long& ul) { ul = 6; }
+void CppyyTestData::set_llong_r(long long& ll) { ll = -7; }
+void CppyyTestData::set_ullong_r(unsigned long long& ull) { ull = 8; }
+void CppyyTestData::set_float_r(float& f) { f = 5.f; }
+void CppyyTestData::set_double_r(double& d) { d = -5.; }
+void CppyyTestData::set_ldouble_r(long double& ld) { ld = 10.l; }
+
+//- setters ptr -------------------------------------------------------------
+void CppyyTestData::set_bool_p(bool* b) { *b = true; }
+void CppyyTestData::set_char_p(char* c) { *c = 'a'; }
+void CppyyTestData::set_wchar_p(wchar_t* wc) { *wc = 'b'; }
+void CppyyTestData::set_char16_p(char16_t* c16) { *c16 = u'\u6c24'; }
+void CppyyTestData::set_char32_p(char32_t* c32) { *c32 = U'\U0001f34e'; }
+void CppyyTestData::set_schar_p(signed char* sc) { *sc = 'c'; }
+void CppyyTestData::set_uchar_p(unsigned char* uc) { *uc = 'd'; }
+#if __cplusplus > 201402L
+void CppyyTestData::set_byte_p(std::byte* b) { *b = (std::byte)'e'; }
+#endif
+void CppyyTestData::set_short_p(short* s) { *s = -1; }
+void CppyyTestData::set_ushort_p(unsigned short* us) { *us = 2; }
+void CppyyTestData::set_int_p(int* i) { *i = -3; }
+void CppyyTestData::set_uint_p(unsigned int* ui) { *ui = 4; }
+void CppyyTestData::set_long_p(long* l) { *l = -5; }
+void CppyyTestData::set_ulong_p(unsigned long* ul) { *ul = 6; }
+void CppyyTestData::set_llong_p(long long* ll) { *ll = -7; }
+void CppyyTestData::set_ullong_p(unsigned long long* ull) { *ull = 8; }
+void CppyyTestData::set_float_p(float* f) { *f = 5.f; }
+void CppyyTestData::set_double_p(double* d) { *d = -5.; }
+void CppyyTestData::set_ldouble_p(long double* ld) { *ld = 10.l; }
+
+//- setters ptrptr ----------------------------------------------------------
+void CppyyTestData::set_bool_ppa(bool** b) {
+ (*b) = new bool[3];
+ (*b)[0] = true; (*b)[1] = false; (*b)[2] = true;
+}
+void CppyyTestData::set_char_ppa(char** c) {
+ (*c) = new char[3];
+ (*c)[0] = 'a'; (*c)[1] = 'b'; (*c)[2] = 'c';
+}
+void CppyyTestData::set_wchar_ppa(wchar_t** wc) {
+ (*wc) = new wchar_t[3];
+ (*wc)[0] = 'd'; (*wc)[1] = 'e'; (*wc)[2] = 'f';
+}
+void CppyyTestData::set_char16_ppa(char16_t** c16) {
+ (*c16) = new char16_t[3];
+ (*c16)[0] = u'\u6c24'; (*c16)[1] = u'\u6c25'; (*c16)[2] = u'\u6c26';
+}
+void CppyyTestData::set_char32_ppa(char32_t** c32) {
+ (*c32) = new char32_t[3];
+ (*c32)[0] = U'\U0001f34d'; (*c32)[1] = U'\U0001f34e'; (*c32)[2] = U'\U0001f34f';
+}
+void CppyyTestData::set_schar_ppa(signed char** sc) {
+ (*sc) = new signed char[3];
+ (*sc)[0] = 'g'; (*sc)[1] = 'h'; (*sc)[2] = 'j';
+}
+void CppyyTestData::set_uchar_ppa(unsigned char** uc) {
+ (*uc) = new unsigned char[3];
+ (*uc)[0] = 'k'; (*uc)[1] = 'l'; (*uc)[2] = 'm';
+}
+#if __cplusplus > 201402L
+void CppyyTestData::set_byte_ppa(std::byte** b) {
+ (*b) = new std::byte[3];
+ (*b)[0] = (std::byte)'n'; (*b)[1] = (std::byte)'o'; (*b)[2] = (std::byte)'p';
+}
+#endif
+void CppyyTestData::set_short_ppa(short** s) {
+ (*s) = new short[3];
+ (*s)[0] = -1; (*s)[1] = -2; (*s)[2] = -3;
+}
+void CppyyTestData::set_ushort_ppa(unsigned short** us) {
+ (*us) = new unsigned short[3];
+ (*us)[0] = 4; (*us)[1] = 5; (*us)[2] = 6;
+}
+void CppyyTestData::set_int_ppa(int** i) {
+ (*i) = new int[3];
+ (*i)[0] = -7; (*i)[1] = -8; (*i)[2] = -9;
+}
+void CppyyTestData::set_uint_ppa(unsigned int** ui) {
+ (*ui) = new unsigned int[3];
+ (*ui)[0] = 10; (*ui)[1] = 11; (*ui)[2] = 12;
+}
+void CppyyTestData::set_long_ppa(long** l) {
+ (*l) = new long[3];
+ (*l)[0] = -13; (*l)[1] = -14; (*l)[2] = -15;
+}
+void CppyyTestData::set_ulong_ppa(unsigned long** ul) {
+ (*ul) = new unsigned long[3];
+ (*ul)[0] = 16; (*ul)[1] = 17; (*ul)[2] = 18;
+}
+void CppyyTestData::set_llong_ppa(long long** ll) {
+ (*ll) = new long long[3];
+ (*ll)[0] = -19; (*ll)[1] = -20; (*ll)[2] = -21;
+}
+void CppyyTestData::set_ullong_ppa(unsigned long long** ull) {
+ (*ull) = new unsigned long long[3];
+ (*ull)[0] = 22; (*ull)[1] = 23; (*ull)[2] = 24;
+}
+void CppyyTestData::set_float_ppa(float** f) {
+ (*f) = new float[3];
+ (*f)[0] = 5.f; (*f)[1] = 10.f; (*f)[2] = 20.f;
+}
+void CppyyTestData::set_double_ppa(double** d) {
+ (*d) = new double[3];
+ (*d)[0] = -5; (*d)[1] = -10.; (*d)[2] = -20.;
+}
+void CppyyTestData::set_ldouble_ppa(long double** ld) {
+ (*ld) = new long double[3];
+ (*ld)[0] = 5.l; (*ld)[1] = 10.f; (*ld)[2] = 20.l;
+}
+
+intptr_t CppyyTestData::set_char_ppm(char** c) {
+ *c = (char*)malloc(4*sizeof(char));
+ return (intptr_t)*c;
+}
+intptr_t CppyyTestData::set_cchar_ppm(const char** cc) {
+ *cc = (const char*)malloc(4*sizeof(char));
+ return (intptr_t)*cc;
+}
+intptr_t CppyyTestData::set_wchar_ppm(wchar_t** w) {
+ *w = (wchar_t*)malloc(4*sizeof(wchar_t));
+ return (intptr_t)*w;
+}
+intptr_t CppyyTestData::set_char16_ppm(char16_t** c16) {
+ *c16 = (char16_t*)malloc(4*sizeof(char16_t));
+ return (intptr_t)*c16;
+}
+intptr_t CppyyTestData::set_char32_ppm(char32_t** c32) {
+ *c32 = (char32_t*)malloc(4*sizeof(char32_t));
+ return (intptr_t)*c32;
+}
+intptr_t CppyyTestData::set_cwchar_ppm(const wchar_t** cw) {
+ *cw = (const wchar_t*)malloc(4*sizeof(wchar_t));
+ return (intptr_t)*cw;
+}
+intptr_t CppyyTestData::set_cchar16_ppm(const char16_t** c16) {
+ *c16 = (const char16_t*)malloc(4*sizeof(char16_t));
+ return (intptr_t)*c16;
+}
+intptr_t CppyyTestData::set_cchar32_ppm(const char32_t** c32) {
+ *c32 = (const char32_t*)malloc(4*sizeof(char32_t));
+ return (intptr_t)*c32;
+}
+intptr_t CppyyTestData::set_void_ppm(void** v) {
+ *v = malloc(4*sizeof(void*));
+ return (intptr_t)*v;
+}
+
+intptr_t CppyyTestData::freeit(void* ptr) {
+ intptr_t out = (intptr_t)ptr;
+ free(ptr);
+ return out;
+}
+
+//- setters r-value ---------------------------------------------------------
+void CppyyTestData::set_bool_rv(bool&& b) { m_bool = b; }
+void CppyyTestData::set_char_rv(char&& c) { m_char = c; }
+void CppyyTestData::set_schar_rv(signed char&& sc) { m_schar = sc; }
+void CppyyTestData::set_uchar_rv(unsigned char&& uc) { m_uchar = uc; }
+void CppyyTestData::set_wchar_rv(wchar_t&& wc) { m_wchar = wc; }
+void CppyyTestData::set_char16_rv(char16_t&& c16) { m_char16 = c16; }
+void CppyyTestData::set_char32_rv(char32_t&& c32) { m_char32 = c32; }
+#if __cplusplus > 201402L
+void CppyyTestData::set_byte_rv(std::byte&& b) { m_byte = b; }
+#endif
+void CppyyTestData::set_int8_rv(int8_t&& s8) { m_int8 = s8; }
+void CppyyTestData::set_uint8_rv(uint8_t&& u8) { m_uint8 = u8; }
+void CppyyTestData::set_short_rv(short&& s) { m_short = s; }
+void CppyyTestData::set_ushort_rv(unsigned short&& us) { m_ushort = us; }
+void CppyyTestData::set_int_rv(int&& i) { m_int = i; }
+void CppyyTestData::set_uint_rv(unsigned int&& ui) { m_uint = ui; }
+void CppyyTestData::set_long_rv(long&& l) { m_long = l; }
+void CppyyTestData::set_ulong_rv(unsigned long&& ul) { m_ulong = ul; }
+void CppyyTestData::set_llong_rv(long long&& ll) { m_llong = ll; }
+void CppyyTestData::set_ullong_rv(unsigned long long&& ull) { m_ullong = ull; }
+void CppyyTestData::set_long64_rv(Long64_t&& l64) { m_long64 = l64; }
+void CppyyTestData::set_ulong64_rv(ULong64_t&& ul64) { m_ulong64 = ul64; }
+void CppyyTestData::set_float_rv(float&& f) { m_float = f; }
+void CppyyTestData::set_double_rv(double&& d) { m_double = d; }
+void CppyyTestData::set_ldouble_rv(long double&& ld) { m_ldouble = ld; }
+void CppyyTestData::set_complex_rv(complex_t&& cd) { m_complex = cd; }
+void CppyyTestData::set_icomplex_rv(icomplex_t&& ci) { m_icomplex = ci; }
+void CppyyTestData::set_enum_rv(EWhat&& w) { m_enum = w; }
//- passers -----------------------------------------------------------------
unsigned char* CppyyTestData::pass_array(unsigned char* a) { return a; }
@@ -249,47 +530,66 @@ long* CppyyTestData::pass_array(long* a) { return a; }
unsigned long* CppyyTestData::pass_array(unsigned long* a) { return a; }
float* CppyyTestData::pass_array(float* a) { return a; }
double* CppyyTestData::pass_array(double* a) { return a; }
+complex_t* CppyyTestData::pass_array(complex_t* a) { return a; }
//- static data members -----------------------------------------------------
-bool CppyyTestData::s_bool = false;
-char CppyyTestData::s_char = 'c';
-signed char CppyyTestData::s_schar = 's';
-unsigned char CppyyTestData::s_uchar = 'u';
-short CppyyTestData::s_short = -101;
-unsigned short CppyyTestData::s_ushort = 255u;
-int CppyyTestData::s_int = -202;
-unsigned int CppyyTestData::s_uint = 202u;
-long CppyyTestData::s_long = -303l;
-unsigned long CppyyTestData::s_ulong = 303ul;
-long long CppyyTestData::s_llong = -404ll;
-unsigned long long CppyyTestData::s_ullong = 404ull;
-Long64_t CppyyTestData::s_long64 = -505ll;
-ULong64_t CppyyTestData::s_ulong64 = 505ull;
-float CppyyTestData::s_float = -606.f;
-double CppyyTestData::s_double = -707.;
-long double CppyyTestData::s_ldouble = -808.l;
-CppyyTestData::EWhat CppyyTestData::s_enum = CppyyTestData::kNothing;
-void* CppyyTestData::s_voidp = (void*)0;
+bool CppyyTestData::s_bool = false;
+char CppyyTestData::s_char = 'c';
+signed char CppyyTestData::s_schar = 's';
+unsigned char CppyyTestData::s_uchar = 'u';
+wchar_t CppyyTestData::s_wchar = L'U';
+char16_t CppyyTestData::s_char16 = u'\u6c29';
+char32_t CppyyTestData::s_char32 = U'\U0001f34b';
+#if __cplusplus > 201402L
+std::byte CppyyTestData::s_byte = (std::byte)'b';
+#endif
+int8_t CppyyTestData::s_int8 = - 87;
+uint8_t CppyyTestData::s_uint8 = 87;
+short CppyyTestData::s_short = -101;
+unsigned short CppyyTestData::s_ushort = 255u;
+int CppyyTestData::s_int = -202;
+unsigned int CppyyTestData::s_uint = 202u;
+long CppyyTestData::s_long = -303l;
+unsigned long CppyyTestData::s_ulong = 303ul;
+long long CppyyTestData::s_llong = -404ll;
+unsigned long long CppyyTestData::s_ullong = 404ull;
+Long64_t CppyyTestData::s_long64 = -505ll;
+ULong64_t CppyyTestData::s_ulong64 = 505ull;
+float CppyyTestData::s_float = -606.f;
+double CppyyTestData::s_double = -707.;
+long double CppyyTestData::s_ldouble = -808.l;
+complex_t CppyyTestData::s_complex = {909., -909.};
+icomplex_t CppyyTestData::s_icomplex = {979, -979};
+CppyyTestData::EWhat CppyyTestData::s_enum = CppyyTestData::kNothing;
+void* CppyyTestData::s_voidp = (void*)0;
+std::string CppyyTestData::s_strv = "Hello";
+std::string* CppyyTestData::s_strp = nullptr;
//- strings -----------------------------------------------------------------
-const char* CppyyTestData::get_valid_string(const char* in) { return in; }
-const char* CppyyTestData::get_invalid_string() { return (const char*)0; }
+const char* CppyyTestData::get_valid_string(const char* in) { return in; }
+const char* CppyyTestData::get_invalid_string() { return (const char*)0; }
+const wchar_t* CppyyTestData::get_valid_wstring(const wchar_t* in) { return in; }
+const wchar_t* CppyyTestData::get_invalid_wstring() { return (const wchar_t*)0; }
+const char16_t* CppyyTestData::get_valid_string16(const char16_t* in) { return in; }
+const char16_t* CppyyTestData::get_invalid_string16() { return (const char16_t*)0; }
+const char32_t* CppyyTestData::get_valid_string32(const char32_t* in) { return in; }
+const char32_t* CppyyTestData::get_invalid_string32() { return (const char32_t*)0; }
//= global functions ========================================================
-long get_pod_address(CppyyTestData& c)
+intptr_t get_pod_address(CppyyTestData& c)
{
- return (long)&c.m_pod;
+ return (intptr_t)&c.m_pod;
}
-long get_int_address(CppyyTestData& c)
+intptr_t get_int_address(CppyyTestData& c)
{
- return (long)&c.m_pod.m_int;
+ return (intptr_t)&c.m_pod.m_int;
}
-long get_double_address(CppyyTestData& c)
+intptr_t get_double_address(CppyyTestData& c)
{
- return (long)&c.m_pod.m_double;
+ return (intptr_t)&c.m_pod.m_double;
}
@@ -298,6 +598,14 @@ bool g_bool = false;
char g_char = 'w';
signed char g_schar = 'v';
unsigned char g_uchar = 'u';
+wchar_t g_wchar = L'U';
+char16_t g_char16 = u'\u6c21';
+char32_t g_char32 = U'\u6c21';
+#if __cplusplus > 201402L
+std::byte g_byte = (std::byte)'x';
+#endif
+int8_t g_int8 = -66;
+uint8_t g_uint8 = 66;
short g_short = -88;
unsigned short g_ushort = 88u;
int g_int = -188;
@@ -311,6 +619,8 @@ ULong64_t g_ulong64 = 488ull;
float g_float = -588.f;
double g_double = -688.;
long double g_ldouble = -788.l;
+complex_t g_complex = {808., -808.};
+icomplex_t g_icomplex = {909, -909};
EFruit g_enum = kBanana;
void* g_voidp = nullptr;
@@ -342,16 +652,150 @@ CppyyTestPod* get_null_pod() {
return (CppyyTestPod*)0;
}
+std::string g_some_global_string = "C++";
+std::string get_some_global_string() { return g_some_global_string; }
+std::string g_some_global_string2 = "C++";
+std::string get_some_global_string2() { return g_some_global_string2; }
+
+const char16_t* g_some_global_string16 = u"z\u00df\u6c34";
+const char32_t* g_some_global_string32 = U"z\u00df\u6c34\U0001f34c";
+
+std::string SomeStaticDataNS::s_some_static_string = "C++";
+std::string SomeStaticDataNS::get_some_static_string() { return s_some_static_string; }
+std::string SomeStaticDataNS::s_some_static_string2 = "C++";
+std::string SomeStaticDataNS::get_some_static_string2() { return s_some_static_string2; }
+
+StorableData gData{5.};
+
+
+//= special case of "byte" arrays ===========================================
+int64_t sum_uc_data(unsigned char* data, int size)
+{
+ int64_t total = 0;
+ for (int i = 0; i < size; ++i) total += int64_t(data[i]);
+ return total;
+}
+
+#if __cplusplus > 201402L
+int64_t sum_byte_data(std::byte* data, int size)
+{
+ return sum_uc_data((unsigned char*)data, size);
+}
+#endif
+
//= function pointer passing ================================================
-int sum_of_int(int i1, int i2) {
+int sum_of_int1(int i1, int i2) {
return i1+i2;
}
+int sum_of_int2(int i1, int i2) {
+ return 2*i1+i2;
+}
+
+int (*sum_of_int_ptr)(int, int) = sum_of_int1;
+
+int call_sum_of_int(int i1, int i2) {
+ if (sum_of_int_ptr)
+ return (*sum_of_int_ptr)(i1, i2);
+ return -1;
+}
+
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);
+double call_double_double(double (*f)(double, double), double d1, double d2) {
+ if (!f) return -1.;
+ return f(d1, d2);
+}
+
+
+//= callable passing ========================================================
+int call_int_int(int (*f)(int, int), int i1, int i2) {
+ return f(i1, i2);
+}
+
+void call_void(void (*f)(int), int i) {
+ f(i);
+}
+
+int call_refi(void (*f)(int&)) {
+ int i = -1; f(i); return i;
+}
+
+int call_refl(void (*f)(long&)) {
+ long l = -1L; f(l); return l;
+}
+
+int call_refd(void (*f)(double&)) {
+ double d = -1.; f(d); return d;
+}
+
+
+StoreCallable::StoreCallable(double (*f)(double, double)) : fF(f) {
+ /* empty */
+}
+
+void StoreCallable::set_callable(double (*f)(double, double)) {
+ fF = f;
+}
+
+double StoreCallable::operator()(double d1, double d2) {
+ return fF(d1, d2);
+}
+
+//= callable through std::function ==========================================
+double call_double_double_sf(const std::function<double(double, double)>& f, double d1, double d2) {
+ return f(d1, d2);
+}
+
+int call_int_int_sf(const std::function<int(int, int)>& f, int i1, int i2) {
+ return f(i1, i2);
+}
+
+void call_void_sf(const std::function<void(int)>& f, int i) {
+ f(i);
+}
+
+int call_refi_sf(const std::function<void(int&)>& f) {
+ int i = -1; f(i); return i;
+}
+
+int call_refl_sf(const std::function<void(long&)>& f) {
+ long l = -1L; f(l); return l;
+}
+
+int call_refd_sf(const std::function<void(double&)>& f) {
+ double d = -1.; f(d); return d;
+}
+
+
+StoreCallable_sf::StoreCallable_sf(const std::function<double(double, double)>& f) : fF(f) {
+ /* empty */
}
+
+void StoreCallable_sf::set_callable(const std::function<double(double, double)>& f) {
+ fF = f;
+}
+
+double StoreCallable_sf::operator()(double d1, double d2) {
+ return fF(d1, d2);
+}
+
+
+//= array of C strings passing ==============================================
+std::vector<std::string> ArrayOfCStrings::takes_array_of_cstrings(const char* args[], int len)
+{
+ std::vector<std::string> v;
+ v.reserve(len);
+ for (int i = 0; i < len; ++i)
+ v.emplace_back(args[i]);
+
+ return v;
+}
+
+
+//= aggregate testing ======================================================
+int AggregateTest::Aggregate1::sInt = 17;
+int AggregateTest::Aggregate2::sInt = 27;
diff --git a/pypy/module/_cppyy/test/datatypes.h b/pypy/module/_cppyy/test/datatypes.h
index 0df18fc68d..0a6cd393a0 100644
--- a/pypy/module/_cppyy/test/datatypes.h
+++ b/pypy/module/_cppyy/test/datatypes.h
@@ -1,13 +1,21 @@
-// copied from RtypesCore.h ...
-#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
+#ifndef CPPYY_TEST_DATATYPES_H
+#define CPPYY_TEST_DATATYPES_H
+
+#ifdef _WIN32
+typedef __int64 Long64_t;
+typedef unsigned __int64 ULong64_t;
#else
-typedef long long Long64_t; //Portable signed long integer 8 bytes
-typedef unsigned long long ULong64_t;//Portable unsigned long integer 8 bytes
+typedef long long Long64_t;
+typedef unsigned long long ULong64_t;
#endif
-
+#include <cstddef>
+#include <cstdint>
+#include <complex>
+#include <functional>
+#include <memory>
#include <vector>
+#include <wchar.h>
+#include <sys/types.h>
const int N = 5;
@@ -25,6 +33,8 @@ extern std::vector<EFruit> vecFruits;
//===========================================================================
+enum class NamedClassEnum { E1 = 42 };
+
namespace EnumSpace {
enum E {E1 = 1, E2};
class EnumClass {
@@ -34,6 +44,8 @@ namespace EnumSpace {
};
typedef enum { AA = 1, BB, CC, DD } letter_code;
+
+ enum class NamedClassEnum { E1 = -42 };
}
@@ -67,6 +79,9 @@ private:
//===========================================================================
+typedef std::complex<double> complex_t; // maps to Py_complex
+typedef std::complex<int> icomplex_t; // no equivalent
+
class CppyyTestData {
public:
CppyyTestData();
@@ -83,6 +98,14 @@ public:
char get_char();
signed char get_schar();
unsigned char get_uchar();
+ wchar_t get_wchar();
+ char16_t get_char16();
+ char32_t get_char32();
+#if __cplusplus > 201402L
+ std::byte get_byte();
+#endif
+ int8_t get_int8();
+ uint8_t get_uint8();
short get_short();
unsigned short get_ushort();
int get_int();
@@ -96,15 +119,22 @@ public:
float get_float();
double get_double();
long double get_ldouble();
- typedef long double aap_t;
- long double get_ldouble_def(long double ld = aap_t(1));
+ long double get_ldouble_def(long double ld = 1);
+ complex_t get_complex();
+ icomplex_t get_icomplex();
EWhat get_enum();
void* get_voidp();
bool* get_bool_array();
bool* get_bool_array2();
+ signed char* get_schar_array();
+ signed char* get_schar_array2();
unsigned char* get_uchar_array();
unsigned char* get_uchar_array2();
+#if __cplusplus > 201402L
+ std::byte* get_byte_array();
+ std::byte* get_byte_array2();
+#endif
short* get_short_array();
short* get_short_array2();
unsigned short* get_ushort_array();
@@ -118,10 +148,12 @@ public:
unsigned long* get_ulong_array();
unsigned long* get_ulong_array2();
- float* get_float_array();
- float* get_float_array2();
- double* get_double_array();
- double* get_double_array2();
+ float* get_float_array();
+ float* get_float_array2();
+ double* get_double_array();
+ double* get_double_array2();
+ complex_t* get_complex_array();
+ complex_t* get_complex_array2();
CppyyTestPod get_pod_val(); // for m_pod
CppyyTestPod* get_pod_val_ptr();
@@ -135,6 +167,14 @@ public:
const char& get_char_cr();
const signed char& get_schar_cr();
const unsigned char& get_uchar_cr();
+ const wchar_t& get_wchar_cr();
+ const char16_t& get_char16_cr();
+ const char32_t& get_char32_cr();
+#if __cplusplus > 201402L
+ const std::byte& get_byte_cr();
+#endif
+ const int8_t& get_int8_cr();
+ const uint8_t& get_uint8_cr();
const short& get_short_cr();
const unsigned short& get_ushort_cr();
const int& get_int_cr();
@@ -148,6 +188,8 @@ public:
const float& get_float_cr();
const double& get_double_cr();
const long double& get_ldouble_cr();
+ const complex_t& get_complex_cr();
+ const icomplex_t& get_icomplex_cr();
const EWhat& get_enum_cr();
// getters ref
@@ -155,6 +197,14 @@ public:
char& get_char_r();
signed char& get_schar_r();
unsigned char& get_uchar_r();
+ wchar_t& get_wchar_r();
+ char16_t& get_char16_r();
+ char32_t& get_char32_r();
+#if __cplusplus > 201402L
+ std::byte& get_byte_r();
+#endif
+ int8_t& get_int8_r();
+ uint8_t& get_uint8_r();
short& get_short_r();
unsigned short& get_ushort_r();
int& get_int_r();
@@ -168,6 +218,8 @@ public:
float& get_float_r();
double& get_double_r();
long double& get_ldouble_r();
+ complex_t& get_complex_r();
+ icomplex_t& get_icomplex_r();
EWhat& get_enum_r();
// setters
@@ -175,6 +227,14 @@ public:
void set_char(char);
void set_schar(signed char);
void set_uchar(unsigned char);
+ void set_wchar(wchar_t);
+ void set_char16(char16_t);
+ void set_char32(char32_t);
+#if __cplusplus > 201402L
+ void set_byte(std::byte);
+#endif
+ void set_int8(int8_t);
+ void set_uint8(uint8_t);
void set_short(short);
void set_ushort(unsigned short);
void set_int(int);
@@ -188,6 +248,8 @@ public:
void set_float(float);
void set_double(double);
void set_ldouble(long double);
+ void set_complex(complex_t);
+ void set_icomplex(icomplex_t);
void set_enum(EWhat);
void set_voidp(void*);
@@ -207,6 +269,14 @@ public:
void set_char_cr(const char&);
void set_schar_cr(const signed char&);
void set_uchar_cr(const unsigned char&);
+ void set_wchar_cr(const wchar_t&);
+ void set_char16_cr(const char16_t&);
+ void set_char32_cr(const char32_t&);
+#if __cplusplus > 201402L
+ void set_byte_cr(const std::byte&);
+#endif
+ void set_int8_cr(const int8_t&);
+ void set_uint8_cr(const uint8_t&);
void set_short_cr(const short&);
void set_ushort_cr(const unsigned short&);
void set_int_cr(const int&);
@@ -220,8 +290,121 @@ public:
void set_float_cr(const float&);
void set_double_cr(const double&);
void set_ldouble_cr(const long double&);
+ void set_complex_cr(const complex_t&);
+ void set_icomplex_cr(const icomplex_t&);
void set_enum_cr(const EWhat&);
+// setters ref
+ void set_bool_r(bool&);
+ void set_char_r(char&);
+ void set_wchar_r(wchar_t&);
+ void set_char16_r(char16_t&);
+ void set_char32_r(char32_t&);
+ void set_schar_r(signed char&);
+ void set_uchar_r(unsigned char&);
+#if __cplusplus > 201402L
+ void set_byte_r(std::byte&);
+#endif
+ void set_short_r(short&);
+ void set_ushort_r(unsigned short&);
+ void set_int_r(int&);
+ void set_uint_r(unsigned int&);
+ void set_long_r(long&);
+ void set_ulong_r(unsigned long&);
+ void set_llong_r(long long&);
+ void set_ullong_r(unsigned long long&);
+ void set_float_r(float&);
+ void set_double_r(double&);
+ void set_ldouble_r(long double&);
+
+// setters ptr
+ void set_bool_p(bool*);
+ void set_char_p(char*);
+ void set_wchar_p(wchar_t*);
+ void set_char16_p(char16_t*);
+ void set_char32_p(char32_t*);
+ void set_schar_p(signed char*);
+ void set_uchar_p(unsigned char*);
+#if __cplusplus > 201402L
+ void set_byte_p(std::byte*);
+#endif
+ void set_short_p(short*);
+ void set_ushort_p(unsigned short*);
+ void set_int_p(int*);
+ void set_uint_p(unsigned int*);
+ void set_long_p(long*);
+ void set_ulong_p(unsigned long*);
+ void set_llong_p(long long*);
+ void set_ullong_p(unsigned long long*);
+ void set_float_p(float*);
+ void set_double_p(double*);
+ void set_ldouble_p(long double*);
+
+// setters ptrptr
+ void set_bool_ppa(bool**);
+ void set_char_ppa(char**);
+ void set_wchar_ppa(wchar_t**);
+ void set_char16_ppa(char16_t**);
+ void set_char32_ppa(char32_t**);
+ void set_schar_ppa(signed char**);
+ void set_uchar_ppa(unsigned char**);
+#if __cplusplus > 201402L
+ void set_byte_ppa(std::byte**);
+#endif
+ void set_short_ppa(short**);
+ void set_ushort_ppa(unsigned short**);
+ void set_int_ppa(int**);
+ void set_uint_ppa(unsigned int**);
+ void set_long_ppa(long**);
+ void set_ulong_ppa(unsigned long**);
+ void set_llong_ppa(long long**);
+ void set_ullong_ppa(unsigned long long**);
+ void set_float_ppa(float**);
+ void set_double_ppa(double**);
+ void set_ldouble_ppa(long double**);
+
+ intptr_t set_char_ppm(char**);
+ intptr_t set_cchar_ppm(const char**);
+ intptr_t set_wchar_ppm(wchar_t**);
+ intptr_t set_char16_ppm(char16_t**);
+ intptr_t set_char32_ppm(char32_t**);
+ intptr_t set_cwchar_ppm(const wchar_t**);
+ intptr_t set_cchar16_ppm(const char16_t**);
+ intptr_t set_cchar32_ppm(const char32_t**);
+ intptr_t set_void_ppm(void**);
+
+ intptr_t freeit(void*);
+
+// setters r-value
+ void set_bool_rv(bool&&);
+ void set_char_rv(char&&);
+ void set_schar_rv(signed char&&);
+ void set_uchar_rv(unsigned char&&);
+ void set_wchar_rv(wchar_t&&);
+ void set_char16_rv(char16_t&&);
+ void set_char32_rv(char32_t&&);
+#if __cplusplus > 201402L
+ void set_byte_rv(std::byte&&);
+#endif
+ void set_int8_rv(int8_t&&);
+ void set_uint8_rv(uint8_t&&);
+ void set_short_rv(short&&);
+ void set_ushort_rv(unsigned short&&);
+ void set_int_rv(int&&);
+ void set_uint_rv(unsigned int&&);
+ void set_long_rv(long&&);
+ void set_ulong_rv(unsigned long&&);
+ void set_llong_rv(long long&&);
+ void set_ullong_rv(unsigned long long&&);
+ void set_long64_rv(Long64_t&&);
+ void set_ulong64_rv(ULong64_t&&);
+ void set_float_rv(float&&);
+ void set_double_rv(double&&);
+ void set_ldouble_rv(long double&&);
+ void set_complex_rv(complex_t&&);
+ void set_icomplex_rv(icomplex_t&&);
+ void set_enum_rv(EWhat&&);
+
// passers
unsigned char* pass_array(unsigned char*);
short* pass_array(short*);
@@ -232,6 +415,7 @@ public:
unsigned long* pass_array(unsigned long*);
float* pass_array(float*);
double* pass_array(double*);
+ complex_t* pass_array(complex_t*);
unsigned char* pass_void_array_B(void* a) { return pass_array((unsigned char*)a); }
short* pass_void_array_h(void* a) { return pass_array((short*)a); }
@@ -242,10 +426,17 @@ public:
unsigned long* pass_void_array_L(void* a) { return pass_array((unsigned long*)a); }
float* pass_void_array_f(void* a) { return pass_array((float*)a); }
double* pass_void_array_d(void* a) { return pass_array((double*)a); }
+ complex_t* pass_void_array_Z(void* a) { return pass_array((complex_t*)a); }
// strings
- const char* get_valid_string(const char* in);
- const char* get_invalid_string();
+ const char* get_valid_string(const char* in);
+ const char* get_invalid_string();
+ const wchar_t* get_valid_wstring(const wchar_t* in);
+ const wchar_t* get_invalid_wstring();
+ const char16_t* get_valid_string16(const char16_t* in);
+ const char16_t* get_invalid_string16();
+ const char32_t* get_valid_string32(const char32_t* in);
+ const char32_t* get_invalid_string32();
public:
// basic types
@@ -253,6 +444,14 @@ public:
char m_char;
signed char m_schar;
unsigned char m_uchar;
+ wchar_t m_wchar;
+ char16_t m_char16;
+ char32_t m_char32;
+#if __cplusplus > 201402L
+ std::byte m_byte;
+#endif
+ int8_t m_int8;
+ uint8_t m_uint8;
short m_short;
unsigned short m_ushort;
int m_int;
@@ -267,14 +466,22 @@ public:
float m_float;
double m_double;
long double m_ldouble;
+ complex_t m_complex;
+ icomplex_t m_icomplex;
EWhat m_enum;
void* m_voidp;
// array types
bool m_bool_array[N];
bool* m_bool_array2;
+ signed char m_schar_array[N];
+ signed char* m_schar_array2;
unsigned char m_uchar_array[N];
unsigned char* m_uchar_array2;
+#if __cplusplus > 201402L
+ std::byte m_byte_array[N];
+ std::byte* m_byte_array2;
+#endif
short m_short_array[N];
short* m_short_array2;
unsigned short m_ushort_array[N];
@@ -288,10 +495,14 @@ public:
unsigned long m_ulong_array[N];
unsigned long* m_ulong_array2;
- float m_float_array[N];
- float* m_float_array2;
- double m_double_array[N];
- double* m_double_array2;
+ float m_float_array[N];
+ float* m_float_array2;
+ double m_double_array[N];
+ double* m_double_array2;
+ complex_t m_complex_array[N];
+ complex_t* m_complex_array2;
+ icomplex_t m_icomplex_array[N];
+ icomplex_t* m_icomplex_array2;
// object types
CppyyTestPod m_pod;
@@ -302,6 +513,14 @@ public:
static char s_char;
static signed char s_schar;
static unsigned char s_uchar;
+ static wchar_t s_wchar;
+ static char16_t s_char16;
+ static char32_t s_char32;
+#if __cplusplus > 201402L
+ static std::byte s_byte;
+#endif
+ static int8_t s_int8;
+ static uint8_t s_uint8;
static short s_short;
static unsigned short s_ushort;
static int s_int;
@@ -315,8 +534,12 @@ public:
static float s_float;
static double s_double;
static long double s_ldouble;
+ static complex_t s_complex;
+ static icomplex_t s_icomplex;
static EWhat s_enum;
static void* s_voidp;
+ static std::string s_strv;
+ static std::string* s_strp;
private:
bool m_owns_arrays;
@@ -324,9 +547,9 @@ private:
//= global functions ========================================================
-long get_pod_address(CppyyTestData& c);
-long get_int_address(CppyyTestData& c);
-long get_double_address(CppyyTestData& c);
+intptr_t get_pod_address(CppyyTestData& c);
+intptr_t get_int_address(CppyyTestData& c);
+intptr_t get_double_address(CppyyTestData& c);
//= global variables/pointers ===============================================
@@ -334,6 +557,14 @@ extern bool g_bool;
extern char g_char;
extern signed char g_schar;
extern unsigned char g_uchar;
+extern wchar_t g_wchar;
+extern char16_t g_char16;
+extern char32_t g_char32;
+#if __cplusplus > 201402L
+extern std::byte g_byte;
+#endif
+extern int8_t g_int8;
+extern uint8_t g_uint8;
extern short g_short;
extern unsigned short g_ushort;
extern int g_int;
@@ -347,6 +578,8 @@ extern ULong64_t g_ulong64;
extern float g_float;
extern double g_double;
extern long double g_ldouble;
+extern complex_t g_complex;
+extern icomplex_t g_icomplex;
extern EFruit g_enum;
extern void* g_voidp;
@@ -354,6 +587,14 @@ static const bool g_c_bool = true;
static const char g_c_char = 'z';
static const signed char g_c_schar = 'y';
static const unsigned char g_c_uchar = 'x';
+static const wchar_t g_c_wchar = L'U';
+static const char16_t g_c_char16 = u'\u6c34';
+static const char32_t g_c_char32 = U'\U0001f34c';
+#if __cplusplus > 201402L
+static const std::byte g_c_byte = (std::byte)'u';
+#endif
+static const int8_t g_c_int8 = -12;
+static const uint8_t g_c_uint8 = 12;
static const short g_c_short = -99;
static const unsigned short g_c_ushort = 99u;
static const int g_c_int = -199;
@@ -367,6 +608,8 @@ static const ULong64_t g_c_ulong64 = 499ull;
static const float g_c_float = -599.f;
static const double g_c_double = -699.;
static const long double g_c_ldouble = -799.l;
+static const complex_t g_c_complex = {1., 2.};
+static const icomplex_t g_c_icomplex = {3, 4};
static const EFruit g_c_enum = kApple;
static const void* g_c_voidp = nullptr;
@@ -381,8 +624,126 @@ void set_global_pod(CppyyTestPod* t);
CppyyTestPod* get_global_pod();
CppyyTestPod* get_null_pod();
+extern std::string g_some_global_string;
+std::string get_some_global_string();
+extern std::string g_some_global_string2;
+std::string get_some_global_string2();
+
+extern const char16_t* g_some_global_string16;
+extern const char32_t* g_some_global_string32;
+
+namespace SomeStaticDataNS {
+ extern std::string s_some_static_string;
+ std::string get_some_static_string();
+ extern std::string s_some_static_string2;
+ std::string get_some_static_string2();
+}
+
+struct StorableData {
+ StorableData(double d) : fData(d) {}
+ double fData;
+};
+
+extern StorableData gData;
+
+
+//= special case of "byte" arrays ===========================================
+int64_t sum_uc_data(unsigned char* data, int size);
+#if __cplusplus > 201402L
+int64_t sum_byte_data(std::byte* data, int size);
+#endif
+
//= function pointer passing ================================================
-int sum_of_int(int i1, int i2);
+int sum_of_int1(int i1, int i2);
+int sum_of_int2(int i1, int i2);
+extern int (*sum_of_int_ptr)(int, int);
+int call_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);
+
+struct sum_of_int_struct {
+ int (*sum_of_int_ptr)(int, int);
+};
+
+//= callable passing ========================================================
+int call_int_int(int (*)(int, int), int, int);
+void call_void(void (*f)(int), int i);
+int call_refi(void (*fcn)(int&));
+int call_refl(void (*fcn)(long&));
+int call_refd(void (*fcn)(double&));
+
+class StoreCallable {
+ double (*fF)(double, double);
+public:
+ StoreCallable(double (*)(double, double));
+ void set_callable(double (*)(double, double));
+ double operator()(double, double);
+};
+
+
+//= callable through std::function ==========================================
+double call_double_double_sf(const std::function<double(double, double)>&, double d1, double d2);
+
+int call_int_int_sf(const std::function<int(int, int)>&, int, int);
+void call_void_sf(const std::function<void(int)>&, int i);
+int call_refi_sf(const std::function<void(int&)>&);
+int call_refl_sf(const std::function<void(long&)>&);
+int call_refd_sf(const std::function<void(double&)>&);
+
+class StoreCallable_sf {
+ std::function<double(double, double)> fF;
+public:
+ StoreCallable_sf(const std::function<double(double, double)>&);
+ void set_callable(const std::function<double(double, double)>&);
+ double operator()(double, double);
+};
+
+
+//= array of struct variants ================================================
+namespace ArrayOfStruct {
+
+struct Foo {
+ int fVal;
+};
+
+struct Bar1 {
+ Bar1() : fArr(new Foo[2]) { fArr[0].fVal = 42; fArr[1].fVal = 13; }
+ Bar1(const Bar1&) = delete;
+ Bar1& operator=(const Bar1&) = delete;
+ ~Bar1() { delete[] fArr; }
+ Foo* fArr;
+};
+
+struct Bar2 {
+ Bar2(int num_foo) : fArr(std::unique_ptr<Foo[]>{new Foo[num_foo]}) {
+ for (int i = 0; i < num_foo; ++i) fArr[i].fVal = 2*i;
+ }
+ std::unique_ptr<Foo[]> fArr;
+};
+
+} // namespace ArrayOfStruct
+
+
+//= array of C strings passing ==============================================
+namespace ArrayOfCStrings {
+ std::vector<std::string> takes_array_of_cstrings(const char* args[], int len);
+}
+
+
+//= aggregate testing ======================================================
+namespace AggregateTest {
+
+struct Aggregate1 {
+ static int sInt;
+};
+
+struct Aggregate2 {
+ static int sInt;
+ int fInt = 42;
+};
+
+}
+
+#endif // !CPPYY_TEST_DATATYPES_H
diff --git a/pypy/module/_cppyy/test/datatypes.xml b/pypy/module/_cppyy/test/datatypes.xml
index dbed585e06..4970ecc547 100644
--- a/pypy/module/_cppyy/test/datatypes.xml
+++ b/pypy/module/_cppyy/test/datatypes.xml
@@ -4,9 +4,11 @@
<class name="FourVector" />
<enum name="EFruit" />
+ <enum name="NamedClassEnum" />
<enum name="EnumSpace::E" />
<class name="EnumSpace::EnumClass" />
<enum name="EnumSpace::letter_code" />
+ <enum name="EnumSpace::NamedClassEnum" />
<function pattern="get_*" />
<function pattern="set_*" />
@@ -17,8 +19,49 @@
<variable name="g_int" />
<variable name="g_pod" />
- <function name="sum_of_int" />
+ <variable name="g_some_global_string" />
+ <function name="get_some_global_string" />
+ <variable name="g_some_global_string2" />
+ <function name="get_some_global_string2" />
+
+ <class name="StorableData" />
+ <variable name="gData" />
+
+ <namespace name="SomeStaticDataNS" />
+ <variable name="SomeStaticDataNS::s_some_static_string" />
+ <function name="SomeStaticDataNS::get_some_static_string" />
+ <variable name="SomeStaticDataNS::s_some_static_string2" />
+ <function name="SomeStaticDataNS::get_some_static_string2" />
+
+ <function name="sum_uc_data" />
+ <function name="sum_byte_data" />
+
+ <function name="sum_of_int1" />
+ <function name="sum_of_int2" />
+ <variable name="sum_of_int_ptr" />
+ <function name="call_sum_of_int" />
<function name="sum_of_double" />
<function name="call_double_double" />
+ <function name="call_int_int" />
+ <function name="call_void" />
+ <class name="StoreCallable" />
+
+ <function name="sum_of_int_sf" />
+ <function name="sum_of_double_sf" />
+ <function name="call_double_double_sf" />
+
+ <function name="call_int_int_sf" />
+ <function name="call_void_sf" />
+ <class name="StoreCallable_sf" />
+
+ <namespace name="ArrayOfStruct" />
+ <class pattern="ArrayOfStruct::*" />
+
+ <namespace name="ArrayOfCStrings" />
+ <function pattern="ArrayOfCStrings::*" />
+
+ <namespace name="AggregateTest" />
+ <struct pattern="AggregateTest::*" />
+
</lcgdict>
diff --git a/pypy/module/_cppyy/test/make_dict_win32.py b/pypy/module/_cppyy/test/make_dict_win32.py
new file mode 100755
index 0000000000..accd03327e
--- /dev/null
+++ b/pypy/module/_cppyy/test/make_dict_win32.py
@@ -0,0 +1,108 @@
+import glob, os, sys, subprocess
+
+USES_PYTHON_CAPI = set(('pythonizables',))
+
+fn = sys.argv[1]
+
+if fn == 'all':
+ all_headers = glob.glob('*.h')
+ for header in all_headers:
+ res = os.system(" ".join(['python', sys.argv[0], header[:-2]]+sys.argv[2:]))
+ if res != 0:
+ sys.exit(res)
+ sys.exit(0)
+else:
+ if fn[-4:] == '.cxx': fn = fn[:-4]
+ elif fn[-2:] == '.h': fn = fn[:-2]
+ if not os.path.exists(fn+'.h'):
+ print("file %s.h does not exist" % (fn,))
+ sys.exit(1)
+
+uses_python_capi = False
+if fn in USES_PYTHON_CAPI:
+ uses_python_capi = True
+
+if os.path.exists(fn+'Dict.dll'):
+ dct_time = os.stat(fn+'Dict.dll').st_mtime
+ if not '-f' in sys.argv:
+ mustbuild = False
+ for ext in ['.h', '.cxx', '.xml']:
+ if os.stat(fn+ext).st_mtime > dct_time:
+ mustbuild = True
+ break
+ if not mustbuild:
+ sys.exit(0)
+
+ # cleanup
+ for fg in set(glob.glob(fn+"_rflx*") + glob.glob(fn+"Dict*") + \
+ glob.glob("*.obj") + glob.glob(fn+"Linkdef.h")):
+ os.remove(fg)
+
+def _get_config_exec():
+ return [sys.executable, '-m', 'cppyy_backend._cling_config']
+
+def get_config(what):
+ config_exec_args = _get_config_exec()
+ config_exec_args.append('--'+what)
+ cli_arg = subprocess.check_output(config_exec_args)
+ return cli_arg.decode("utf-8").strip()
+
+def get_python_include_dir():
+ incdir = subprocess.check_output([sys.executable, '-c', "import sysconfig; print(sysconfig.get_path('include'))"])
+ return incdir.decode("utf-8").strip()
+
+def get_python_lib_dir():
+ libdir = subprocess.check_output([sys.executable, '-c', "import sysconfig; print(sysconfig.get_path('stdlib'))"])
+ return os.path.join(os.path.dirname(libdir.decode("utf-8").strip()), 'libs')
+
+# genreflex option
+#DICTIONARY_CMD = "genreflex {fn}.h --selection={fn}.xml --rootmap={fn}Dict.rootmap --rootmap-lib={fn}Dict.dll".format(fn=fn)
+
+with open(fn+'Linkdef.h', 'w') as linkdef:
+ linkdef.write("#ifdef __CLING__\n\n")
+ linkdef.write("#pragma link C++ defined_in %s.h;\n" % fn)
+ linkdef.write("\n#endif")
+
+DICTIONARY_CMD = "python -m cppyy_backend._rootcling -f {fn}_rflx.cxx -rmf {fn}Dict.rootmap -rml {fn}Dict.dll {fn}.h {fn}Linkdef.h".format(fn=fn)
+if os.system(DICTIONARY_CMD):
+ sys.exit(1)
+
+import platform
+if '64' in platform.architecture()[0]:
+ PLATFORMFLAG = '-D_AMD64_'
+ MACHINETYPE = 'X64'
+else:
+ PLATFORMFLAG = '-D_X86_'
+ MACHINETYPE = 'IX86'
+
+cppflags = get_config('cppflags')
+if uses_python_capi:
+ cppflags += ' -I"' + get_python_include_dir() + '"'
+BUILDOBJ_CMD_PART = "cl -O2 -nologo -TP -c -nologo " + cppflags + " -FIsehmap.h -Zc:__cplusplus -MD -GR -D_WINDOWS -DWIN32 " + PLATFORMFLAG + " -EHsc- -W3 -wd4141 -wd4291 -wd4244 -wd4049 -D_XKEYCHECK_H -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -DNOMINMAX -D_CRT_SECURE_NO_WARNINGS {fn}.cxx -Fo{fn}.obj"
+BUILDOBJ_CMD = BUILDOBJ_CMD_PART.format(fn=fn)
+if os.system(BUILDOBJ_CMD):
+ sys.exit(1)
+BUILDOBJ_CMD = BUILDOBJ_CMD_PART.format(fn=fn+'_rflx')
+if os.system(BUILDOBJ_CMD):
+ sys.exit(1)
+
+import cppyy_backend
+CREATEDEF_CMD = "python bindexplib.py {fn} {fn}Dict".format(fn=fn)
+if os.system(CREATEDEF_CMD):
+ sys.exit(1)
+
+ldflags = ''
+if uses_python_capi:
+ ldflags = ' /LIBPATH:"' + get_python_lib_dir() + '" '
+CREATELIB_CMD = ("lib -nologo -MACHINE:" + MACHINETYPE + " -out:{fn}Dict.lib {fn}.obj {fn}_rflx.obj -def:{fn}Dict.def " + ldflags).format(fn=fn)
+if os.system(CREATELIB_CMD):
+ sys.exit(1)
+
+ldflags += get_config('ldflags')
+LINKDLL_CMD = ("link -nologo {fn}.obj {fn}_rflx.obj -DLL -out:{fn}Dict.dll {fn}Dict.exp " + ldflags).format(fn=fn)
+if os.system(LINKDLL_CMD):
+ sys.exit(1)
+
+# cleanup
+for fg in set(glob.glob(fn+"_rflx.cxx*") + glob.glob("*.obj") + glob.glob(fn+"Linkdef.h")):
+ os.remove(fg)
diff --git a/pypy/module/_cppyy/test/support.py b/pypy/module/_cppyy/test/support.py
index e8cd75e327..f403e48912 100644
--- a/pypy/module/_cppyy/test/support.py
+++ b/pypy/module/_cppyy/test/support.py
@@ -5,6 +5,28 @@ currpath = py.path.local(__file__).dirpath()
def setup_make(targetname):
if sys.platform == 'win32':
- py.test.skip('Cannot run this Makefile on windows')
- from rpython.translator.platform import platform as compiler
- compiler.execute_makefile(currpath, [targetname])
+ popen = subprocess.Popen([sys.executable, "make_dict_win32.py", targetname], cwd=str(currpath),
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ else:
+ popen = subprocess.Popen(["make", targetname+"Dict.so"], cwd=str(currpath),
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ stdout, _ = popen.communicate()
+ if popen.returncode:
+ raise OSError("'make' failed:\n%s" % (stdout,))
+
+if sys.hexversion >= 0x3000000:
+ maxvalue = sys.maxsize
+else:
+ maxvalue = sys.maxint
+
+IS_WINDOWS = 0
+if 'win32' in sys.platform:
+ soext = '.dll'
+ import platform
+ if '64' in platform.architecture()[0]:
+ IS_WINDOWS = 64
+ maxvalue = 2**31-1
+ else:
+ IS_WINDOWS = 32
+else:
+ soext = '.so'
diff --git a/pypy/module/_cppyy/test/templates.cxx b/pypy/module/_cppyy/test/templates.cxx
index bc5ff8bc2b..90c3ec48e6 100644
--- a/pypy/module/_cppyy/test/templates.cxx
+++ b/pypy/module/_cppyy/test/templates.cxx
@@ -35,3 +35,22 @@ void some_empty() {
template void some_empty<int>();
} // namespace T_WithRValue
+
+
+// The following is hidden from the Cling interpreter, but available to the
+// linker; it allows for testing whether a function return is picked up from
+// the compiled instantation or from the interpreter.
+
+namespace FailedTypeDeducer {
+
+template<class T>
+class A {
+public:
+ T result() { return T{42}; }
+};
+
+template class A<int>;
+
+template class B<int>;
+
+} // namespace FailedTypeDeducer
diff --git a/pypy/module/_cppyy/test/templates.h b/pypy/module/_cppyy/test/templates.h
index 98c76db3d1..0b86e08e8a 100644
--- a/pypy/module/_cppyy/test/templates.h
+++ b/pypy/module/_cppyy/test/templates.h
@@ -18,8 +18,6 @@
#define INLINE
#endif
-
-
#ifndef __MSC_VER
#include <cxxabi.h>
INLINE std::string demangle_it(const char* name, const char* errmsg) {
@@ -324,9 +322,13 @@ bool is_valid(T&& new_value) {
// variadic templates
namespace some_variadic {
-#ifdef WIN32
+#ifdef _WIN32
+#ifdef __CLING__
extern __declspec(dllimport) std::string gTypeName;
#else
+extern __declspec(dllexport) std::string gTypeName;
+#endif
+#else
extern std::string gTypeName;
#endif
@@ -423,9 +425,13 @@ T fn_T(Args&&... args) {
// template with empty body
namespace T_WithEmptyBody {
-#ifdef WIN32
+#ifdef _WIN32
+#ifdef __CLING__
extern __declspec(dllimport) std::string side_effect;
#else
+extern __declspec(dllexport) std::string side_effect;
+#endif
+#else
extern std::string side_effect;
#endif
@@ -492,4 +498,45 @@ public:
} // namespace TemplateWithSetItem
+
+//===========================================================================
+// type reduction examples on gmpxx-like template expressions
+namespace TypeReduction {
+
+template <typename T>
+struct BinaryExpr;
+
+template <typename T>
+struct Expr {
+ Expr() {}
+ Expr(const BinaryExpr<T>&) {}
+};
+
+template <typename T>
+struct BinaryExpr {
+ BinaryExpr(const Expr<T>&, const Expr<T>&) {}
+};
+
+template<typename T>
+BinaryExpr<T> operator+(const Expr<T>& e1, const Expr<T>& e2) {
+ return BinaryExpr<T>(e1, e2);
+}
+
+} // namespace TypeReduction
+
+
+//===========================================================================
+// type deduction examples
+namespace FailedTypeDeducer {
+
+template<class T>
+class B {
+public:
+ auto result() { return 5.; }
+};
+
+extern template class B<int>;
+
+}
+
#endif // !CPPYY_TEST_TEMPLATES_H
diff --git a/pypy/module/_cppyy/test/templates.xml b/pypy/module/_cppyy/test/templates.xml
index 63d9829332..8bda6eede5 100644
--- a/pypy/module/_cppyy/test/templates.xml
+++ b/pypy/module/_cppyy/test/templates.xml
@@ -33,4 +33,11 @@
<namespace name="T_WithGreedyOverloads" />
<class pattern="T_WithGreedyOverloads::*" />
+ <namespace name="TypeReduction" />
+ <class pattern="TypeReduction::*" />
+ <function pattern="TypeReduction::*" />
+
+ <namespace name="FailedTypeDeducer" />
+ <class pattern="FailedTypeDeducer::*" />
+
</lcgdict>
diff --git a/pypy/module/_cppyy/test/test_advancedcpp.py b/pypy/module/_cppyy/test/test_advancedcpp.py
index 6603b7ed75..6ae146df57 100644
--- a/pypy/module/_cppyy/test/test_advancedcpp.py
+++ b/pypy/module/_cppyy/test/test_advancedcpp.py
@@ -1,12 +1,12 @@
import py, os, sys
-from .support import setup_make
+from .support import setup_make, soext
currpath = py.path.local(__file__).dirpath()
-test_dct = str(currpath.join("advancedcppDict.so"))
+test_dct = str(currpath.join("advancedcppDict"))+soext
def setup_module(mod):
- setup_make("advancedcppDict.so")
+ setup_make("advancedcpp")
def setup_module(mod):
if sys.platform == 'win32':
diff --git a/pypy/module/_cppyy/test/test_boost.py b/pypy/module/_cppyy/test/test_boost.py
new file mode 100644
index 0000000000..a8e2e4d0f2
--- /dev/null
+++ b/pypy/module/_cppyy/test/test_boost.py
@@ -0,0 +1,185 @@
+import py, os, sys
+from pytest import mark, raises
+from .support import setup_make
+
+noboost = False
+if not (os.path.exists(os.path.join(os.path.sep, 'usr', 'include', 'boost')) or \
+ os.path.exists(os.path.join(os.path.sep, 'usr', 'local', 'include', 'boost'))):
+ noboost = True
+
+
+@mark.skipif(noboost == True, reason="boost not found")
+class AppTestBOOSTANY:
+ spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
+
+ def setup_class(cls):
+ cls.space.appexec([], """():
+ import ctypes, _cppyy
+ _cppyy._post_import_startup()
+ _cppyy.gbl.gInterpreter.Declare('#include "boost/any.hpp"')
+ """)
+
+ def test01_any_class(self):
+ """Availability of boost::any"""
+
+ import _cppyy as cppyy
+
+ assert cppyy.gbl.boost.any
+
+ std = cppyy.gbl.std
+ any = cppyy.gbl.boost.any
+
+ assert std.list[any]
+
+ def test02_any_usage(self):
+ """boost::any assignment and casting"""
+
+ import _cppyy as cppyy
+
+ assert cppyy.gbl.boost
+
+ std = cppyy.gbl.std
+ boost = cppyy.gbl.boost
+
+ val = boost.any()
+ # test both by-ref and by rvalue
+ v = std.vector[int]()
+ val.__assign__(v)
+ val.__assign__(std.move(std.vector[int](range(100))))
+ assert val.type() == cppyy.typeid(std.vector[int])
+
+ extract = boost.any_cast[std.vector[int]](val)
+ assert type(extract) is std.vector[int]
+ assert len(extract) == 100
+ extract += range(100)
+ assert len(extract) == 200
+
+ val.__assign__(std.move(extract)) # move forced
+ #assert len(extract) == 0 # not guaranteed by the standard
+
+ # TODO: we hit boost::any_cast<int>(boost::any* operand) instead
+ # of the reference version which raises
+ boost.any_cast.__useffi__ = False
+ try:
+ # raises(Exception, boost.any_cast[int], val)
+ assert not boost.any_cast[int](val)
+ except Exception:
+ # getting here is good, too ...
+ pass
+
+ extract = boost.any_cast[std.vector[int]](val)
+ assert len(extract) == 200
+
+
+@mark.skipif(noboost == True, reason="boost not found")
+class AppTestBOOSTOPERATORS:
+ spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
+
+ def setup_class(cls):
+ cls.space.appexec([], """():
+ import ctypes, _cppyy
+ _cppyy._post_import_startup()
+ _cppyy.gbl.gInterpreter.Declare('#include "boost/operators.hpp"')
+ """)
+
+ def test01_ordered(self):
+ """ordered_field_operators as base used to crash"""
+
+ import _cppyy as cppyy
+
+ cppyy.gbl.gInterpreter.Declare('#include "gmpxx.h"')
+ cppyy.gbl.gInterpreter.Declare("""
+ namespace boost_test {
+ class Derived : boost::ordered_field_operators<Derived>, boost::ordered_field_operators<Derived, mpq_class> {};
+ }
+ """)
+
+ assert cppyy.gbl.boost_test.Derived
+
+
+@mark.skipif(noboost == True, reason="boost not found")
+class AppTestBOOSTVARIANT:
+ spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
+
+ def setup_class(cls):
+ cls.space.appexec([], """():
+ import ctypes, _cppyy
+ _cppyy._post_import_startup()
+ _cppyy.gbl.gInterpreter.Declare('#include "boost/variant/variant.hpp"')
+ _cppyy.gbl.gInterpreter.Declare('#include "boost/variant/get.hpp"')
+ """)
+
+ def test01_variant_usage(self):
+ """boost::variant usage"""
+
+ # as posted on stackoverflow as example
+ import _cppyy as cppyy
+
+ try:
+ cpp = cppyy.gbl
+ except:
+ pass
+
+ cpp = cppyy.gbl
+ std = cpp.std
+ boost = cpp.boost
+
+ cppyy.gbl.gInterpreter.Declare("""namespace BV {
+ class A { };
+ class B { };
+ class C { }; } """)
+
+ VariantType = boost.variant['BV::A, BV::B, BV::C']
+ VariantTypeList = std.vector[VariantType]
+
+ v = VariantTypeList()
+
+ v.push_back(VariantType(cpp.BV.A()))
+ assert v.back().which() == 0
+ v.push_back(VariantType(cpp.BV.B()))
+ assert v.back().which() == 1
+ v.push_back(VariantType(cpp.BV.C()))
+ assert v.back().which() == 2
+
+ assert type(boost.get['BV::A'](v[0])) == cpp.BV.A
+ raises(Exception, boost.get['BV::B'], v[0])
+ assert type(boost.get['BV::B'](v[1])) == cpp.BV.B
+ assert type(boost.get['BV::C'](v[2])) == cpp.BV.C
+
+
+@mark.skipif(noboost == True, reason="boost not found")
+class AppTestBOOSTERASURE:
+ spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
+
+ def setup_class(cls):
+ cls.space.appexec([], """():
+ import ctypes, _cppyy
+ _cppyy._post_import_startup()
+ _cppyy.gbl.gInterpreter.Declare('#include "boost/type_erasure/any.hpp"')
+ _cppyy.gbl.gInterpreter.Declare('#include "boost/type_erasure/member.hpp"')
+ """)
+
+ def test01_erasure_usage(self):
+ """boost::type_erasure usage"""
+
+ import _cppyy as cppyy
+
+ cppyy.gbl.gInterpreter.Declare("""
+ BOOST_TYPE_ERASURE_MEMBER((has_member_f), f, 0)
+
+ using LengthsInterface = boost::mpl::vector<
+ boost::type_erasure::copy_constructible<>,
+ has_member_f<std::vector<int>() const>>;
+
+ using Lengths = boost::type_erasure::any<LengthsInterface>;
+
+ struct Unerased {
+ std::vector<int> f() const { return std::vector<int>{}; }
+ };
+
+ Lengths lengths() {
+ return Unerased{};
+ }
+ """)
+
+ assert cppyy.gbl.lengths() is not None
diff --git a/pypy/module/_cppyy/test/test_cpp11features.py b/pypy/module/_cppyy/test/test_cpp11features.py
index 10a45fd110..7b284befa7 100644
--- a/pypy/module/_cppyy/test/test_cpp11features.py
+++ b/pypy/module/_cppyy/test/test_cpp11features.py
@@ -1,12 +1,12 @@
import py, os, sys
-from .support import setup_make
-
+from .support import setup_make, soext
currpath = py.path.local(__file__).dirpath()
-test_dct = str(currpath.join("cpp11featuresDict.so"))
+test_dct = str(currpath.join("cpp11featuresDict"))+soext
def setup_module(mod):
- setup_make("cpp11featuresDict.so")
+ setup_make("cpp11features")
+
class AppTestCPP11FEATURES:
spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
diff --git a/pypy/module/_cppyy/test/test_cppyy.py b/pypy/module/_cppyy/test/test_cppyy.py
index 55a4929742..e55d19e428 100644
--- a/pypy/module/_cppyy/test/test_cppyy.py
+++ b/pypy/module/_cppyy/test/test_cppyy.py
@@ -1,14 +1,13 @@
import py, os, sys
-
from pypy.module._cppyy import interp_cppyy, executor
-from .support import setup_make
-
+from .support import setup_make, soext
currpath = py.path.local(__file__).dirpath()
-test_dct = str(currpath.join("example01Dict.so"))
+test_dct = str(currpath.join("example01Dict"))+soext
def setup_module(mod):
- setup_make("example01Dict.so")
+ setup_make("example01")
+
class TestCPPYYImplementation:
def test01_class_query(self, space):
diff --git a/pypy/module/_cppyy/test/test_crossing.py b/pypy/module/_cppyy/test/test_crossing.py
index e689c60081..0b371acaae 100644
--- a/pypy/module/_cppyy/test/test_crossing.py
+++ b/pypy/module/_cppyy/test/test_crossing.py
@@ -1,5 +1,5 @@
import py, os, sys
-from .support import setup_make
+from .support import setup_make, soext
from pypy.interpreter.gateway import interp2app, unwrap_spec
from rpython.translator.tool.cbuild import ExternalCompilationInfo
@@ -10,12 +10,12 @@ from rpython.tool.udir import udir
from pypy.module.cpyext import api
from pypy.module.cpyext.state import State
-
currpath = py.path.local(__file__).dirpath()
-test_dct = str(currpath.join("crossingDict.so"))
+test_dct = str(currpath.join("crossingDict"))+soext
def setup_module(mod):
- setup_make("crossingDict.so")
+ setup_make("crossing")
+
# from pypy/module/cpyext/test/test_cpyext.py; modified to accept more external
# symbols and called directly instead of import_module
diff --git a/pypy/module/_cppyy/test/test_datatypes.py b/pypy/module/_cppyy/test/test_datatypes.py
index 0a5d26a428..d127020903 100644
--- a/pypy/module/_cppyy/test/test_datatypes.py
+++ b/pypy/module/_cppyy/test/test_datatypes.py
@@ -1,12 +1,13 @@
import py, os, sys
-from .support import setup_make
-
+from pytest import raises
+from .support import setup_make, soext
currpath = py.path.local(__file__).dirpath()
-test_dct = str(currpath.join("datatypesDict.so"))
+test_dct = str(currpath.join("datatypesDict"))+soext
def setup_module(mod):
- setup_make("datatypesDict.so")
+ setup_make("datatypes")
+
class AppTestDATATYPES:
spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
@@ -17,12 +18,24 @@ class AppTestDATATYPES:
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
+ cls.w_N = cls.space.appexec([], """():
+ import _cppyy
+ return _cppyy.gbl.N""")
+ cls.w_has_byte = cls.space.appexec([], """():
+ import _cppyy
+ return 201402 < _cppyy.gbl.gInterpreter.ProcessLine("__cplusplus;")""")
def test01_instance_data_read_access(self):
"""Read access to instance public data and verify values"""
+ import sys
import _cppyy as cppyy
+
+ if sys.hexversion >= 0x3000000:
+ pyunicode = str
+ else:
+ pyunicode = unicode
+
CppyyTestData = cppyy.gbl.CppyyTestData
c = CppyyTestData()
@@ -36,8 +49,18 @@ class AppTestDATATYPES:
assert c.m_char == 'a'
assert c.m_schar == 'b'
assert c.m_uchar == 'c'
+ assert type(c.m_wchar) == pyunicode
+ assert c.m_wchar == u'D'
+ assert type(c.m_char16) == pyunicode
+ assert c.m_char16 == u'\u00df'
+ assert type(c.m_char32) == pyunicode
+ assert c.m_char32 == u'\u00df'
# reading integer types
+ assert c.m_int8 == - 9; assert c.get_int8_cr() == - 9; assert c.get_int8_r() == - 9
+ assert c.m_uint8 == 9; assert c.get_uint8_cr() == 9; assert c.get_uint8_r() == 9
+ if self.has_byte:
+ assert c.m_byte == ord('d'); assert c.get_byte_cr() == ord('d'); assert c.get_byte_r() == ord('d')
assert c.m_short == -11; assert c.get_short_cr() == -11; assert c.get_short_r() == -11
assert c.m_ushort == 11; assert c.get_ushort_cr() == 11; assert c.get_ushort_r() == 11
assert c.m_int == -22; assert c.get_int_cr() == -22; assert c.get_int_r() == -22
@@ -62,7 +85,7 @@ class AppTestDATATYPES:
assert round(c.get_ldouble_def() -1., 24) == 0
assert round(c.get_ldouble_def(2) -2., 24) == 0
- """# complex<double> type
+ # complex<double> type
assert type(c.get_complex()) == complex
assert round(c.get_complex().real - 99., 11) == 0
assert round(c.get_complex().imag - 101., 11) == 0
@@ -72,6 +95,7 @@ class AppTestDATATYPES:
assert round(c.get_complex_r().real - 99., 11) == 0
assert round(c.get_complex_r().imag - 101., 11) == 0
assert complex(cppyy.gbl.std.complex['double'](1, 2)) == complex(1, 2)
+ assert repr(cppyy.gbl.std.complex['double'](1, 2)) == '(1+2j)'
# complex<int> retains C++ type in all cases (but includes pythonization to
# resemble Python's complex more closely
@@ -84,7 +108,7 @@ class AppTestDATATYPES:
assert type(c.get_icomplex_r()) == cppyy.gbl.std.complex[int]
assert round(c.get_icomplex_r().real - 121., 11) == 0
assert round(c.get_icomplex_r().imag - 141., 11) == 0
- assert complex(cppyy.gbl.std.complex['int'](1, 2)) == complex(1, 2)"""
+ assert complex(cppyy.gbl.std.complex['int'](1, 2)) == complex(1, 2)
# reading of enum types
assert c.m_enum == CppyyTestData.kNothing
@@ -98,8 +122,10 @@ class AppTestDATATYPES:
assert c.get_bool_array2()[i] == bool((i+1)%2)
# reading of integer array types
- names = ['uchar', 'short', 'ushort', 'int', 'uint', 'long', 'ulong']
- alpha = [ (1, 2), (-1, -2), (3, 4), (-5, -6), (7, 8), (-9, -10), (11, 12)]
+ names = ['schar', 'uchar', 'short', 'ushort', 'int', 'uint', 'long', 'ulong']
+ alpha = [ (1, 2), (1, 2), (-1, -2), (3, 4), (-5, -6), (7, 8), (-9, -10), (11, 12)]
+ if self.has_byte: names.append('byte'); alpha.append((3,4))
+
for j in range(self.N):
assert getattr(c, 'm_%s_array' % names[i])[i] == alpha[i][0]*i
assert getattr(c, 'get_%s_array' % names[i])()[i] == alpha[i][0]*i
@@ -114,7 +140,10 @@ class AppTestDATATYPES:
assert round(c.m_double_array2[k] + 16.*k, 8) == 0
# out-of-bounds checks
+ raises(IndexError, c.m_schar_array.__getitem__, self.N)
raises(IndexError, c.m_uchar_array.__getitem__, self.N)
+ if self.has_byte:
+ raises(IndexError, c.m_byte_array.__getitem__, self.N)
raises(IndexError, c.m_short_array.__getitem__, self.N)
raises(IndexError, c.m_ushort_array.__getitem__, self.N)
raises(IndexError, c.m_int_array.__getitem__, self.N)
@@ -136,7 +165,14 @@ class AppTestDATATYPES:
def test02_instance_data_write_access(self):
"""Test write access to instance public data and verify values"""
+ import sys
import _cppyy as cppyy
+
+ if sys.hexversion >= 0x3000000:
+ pyunicode = str
+ else:
+ pyunicode = unicode
+
CppyyTestData = cppyy.gbl.CppyyTestData
c = CppyyTestData()
@@ -152,11 +188,15 @@ class AppTestDATATYPES:
c.m_bool = 0; assert c.get_bool() == False
c.set_bool(0); assert c.m_bool == False
- raises(ValueError, 'c.set_bool(10)')
+ raises(ValueError, c.set_bool, 10)
# char types through functions
c.set_char('c'); assert c.get_char() == 'c'
c.set_uchar('e'); assert c.get_uchar() == 'e'
+ c.set_wchar(u'F'); assert c.get_wchar() == u'F'
+ assert type(c.get_wchar()) == pyunicode
+ c.set_char16(u'\u00f2'); assert c.get_char16() == u'\u00f2'
+ c.set_char32(u'\U0001f31c'); assert c.get_char32() == u'\U0001f31c'
# char types through data members
c.m_char = 'b'; assert c.get_char() == 'b'
@@ -167,14 +207,25 @@ class AppTestDATATYPES:
c.m_uchar = 42; assert c.get_uchar() == chr(42)
c.set_uchar('e'); assert c.m_uchar == 'e'
c.set_uchar(43); assert c.m_uchar == chr(43)
-
- raises(ValueError, 'c.set_char("string")')
- raises(ValueError, 'c.set_char(500)')
- raises(ValueError, 'c.set_uchar("string")')
- raises(ValueError, 'c.set_uchar(-1)')
+ c.m_wchar = u'G'; assert c.get_wchar() == u'G'
+ c.set_wchar(u'H'); assert c.m_wchar == u'H'
+ c.m_char16 = u'\u00f3'; assert c.get_char16() == u'\u00f3'
+ c.set_char16(u'\u00f4'); assert c.m_char16 == u'\u00f4'
+ c.m_char32 = u'\U0001f31d'; assert c.get_char32() == u'\U0001f31d'
+ c.set_char32(u'\U0001f31e'); assert c.m_char32 == u'\U0001f31e'
+
+ raises(ValueError, c.set_char, "string")
+ raises(ValueError, c.set_char, 500)
+ raises(ValueError, c.set_uchar, "string")
+ raises(ValueError, c.set_uchar, -1)
+ raises(ValueError, c.set_wchar, "string")
+ raises(ValueError, c.set_char16, "string")
+ raises(ValueError, c.set_char32, "string")
# integer types
- names = ['short', 'ushort', 'int', 'uint', 'long', 'ulong', 'llong', 'ullong']
+ names = ['int8', 'uint8', 'short', 'ushort', 'int', 'uint', 'long', 'ulong', 'llong', 'ullong']
+ if self.has_byte: names.append('byte')
+
for i in range(len(names)):
setattr(c, 'm_'+names[i], i)
assert eval('c.get_%s()' % names[i]) == i
@@ -208,9 +259,12 @@ class AppTestDATATYPES:
# integer arrays
names = ['uchar', 'short', 'ushort', 'int', 'uint', 'long', 'ulong']
+ if self.has_byte: names.append('byte')
+
import array
a = range(self.N)
atypes = ['B', 'h', 'H', 'i', 'I', 'l', 'L']
+ if self.has_byte: atypes.append('B')
for j in range(len(names)):
b = array.array(atypes[j], a)
setattr(c, 'm_'+names[j]+'_array', b) # buffer copies
@@ -269,7 +323,16 @@ class AppTestDATATYPES:
def test04_class_read_access(self):
"""Test read access to class public data and verify values"""
- import _cppyy as cppyy, sys
+ import sys
+ import _cppyy as cppyy
+
+ if sys.hexversion >= 0x3000000:
+ pylong = int
+ pyunicode = str
+ else:
+ pylong = long
+ pyunicode = unicode
+
CppyyTestData = cppyy.gbl.CppyyTestData
c = CppyyTestData()
@@ -278,10 +341,30 @@ class AppTestDATATYPES:
# char types
assert CppyyTestData.s_char == 'c'
assert c.s_char == 'c'
- assert c.s_uchar == 'u'
assert CppyyTestData.s_uchar == 'u'
+ assert c.s_uchar == 'u'
+ assert CppyyTestData.s_wchar == u'U'
+ assert c.s_wchar == u'U'
+ assert CppyyTestData.s_char16 == u'\u6c29'
+ assert c.s_char16 == u'\u6c29'
+ assert CppyyTestData.s_char32 == u'\U0001f34b'
+ assert c.s_char32 == u'\U0001f34b'
+
+ assert type(c.s_wchar) == pyunicode
+ assert type(CppyyTestData.s_wchar) == pyunicode
+ assert type(c.s_char16) == pyunicode
+ assert type(CppyyTestData.s_char16) == pyunicode
+ assert type(c.s_char32) == pyunicode
+ assert type(CppyyTestData.s_char32) == pyunicode
# integer types
+ if self.has_byte:
+ assert CppyyTestData.s_byte == ord('b')
+ assert c.s_byte == ord('b')
+ assert CppyyTestData.s_int8 == - 87
+ assert c.s_int8 == - 87
+ assert CppyyTestData.s_uint8 == 87
+ assert c.s_uint8 == 87
assert CppyyTestData.s_short == -101
assert c.s_short == -101
assert c.s_ushort == 255
@@ -290,14 +373,14 @@ class AppTestDATATYPES:
assert c.s_int == -202
assert c.s_uint == 202
assert CppyyTestData.s_uint == 202
- assert CppyyTestData.s_long == -303
- assert c.s_long == -303
- assert c.s_ulong == 303
- assert CppyyTestData.s_ulong == 303
- assert CppyyTestData.s_llong == -404
- assert c.s_llong == -404
- assert c.s_ullong == 404
- assert CppyyTestData.s_ullong == 404
+ assert CppyyTestData.s_long == -pylong(303)
+ assert c.s_long == -pylong(303)
+ assert c.s_ulong == pylong(303)
+ assert CppyyTestData.s_ulong == pylong(303)
+ assert CppyyTestData.s_llong == -pylong(404)
+ assert c.s_llong == -pylong(404)
+ assert c.s_ullong == pylong(404)
+ assert CppyyTestData.s_ullong == pylong(404)
# floating point types
assert round(CppyyTestData.s_float + 606., 5) == 0
@@ -312,7 +395,14 @@ class AppTestDATATYPES:
def test05_class_data_write_access(self):
"""Test write access to class public data and verify values"""
- import _cppyy as cppyy, sys
+ import sys
+ import _cppyy as cppyy
+
+ if sys.hexversion >= 0x3000000:
+ pylong = int
+ else:
+ pylong = long
+
CppyyTestData = cppyy.gbl.CppyyTestData
c = CppyyTestData()
@@ -329,8 +419,25 @@ class AppTestDATATYPES:
assert CppyyTestData.s_uchar == 'd'
raises(ValueError, setattr, CppyyTestData, 's_uchar', -1)
raises(ValueError, setattr, c, 's_uchar', -1)
+ CppyyTestData.s_wchar = u'K'
+ assert c.s_wchar == u'K'
+ c.s_wchar = u'L'
+ assert CppyyTestData.s_wchar == u'L'
+ CppyyTestData.s_char16 = u'\u00df'
+ assert c.s_char16 == u'\u00df'
+ c.s_char16 = u'\u00ef'
+ assert CppyyTestData.s_char16 == u'\u00ef'
+ CppyyTestData.s_char32 = u'\u00df'
+ assert c.s_char32 == u'\u00df'
+ c.s_char32 = u'\u00ef'
+ assert CppyyTestData.s_char32 == u'\u00ef'
# integer types
+ if self.has_byte:
+ c.s_byte = 66
+ assert CppyyTestData.s_byte == 66
+ CppyyTestData.s_byte = 66
+ assert c.s_byte == 66
c.s_short = -102
assert CppyyTestData.s_short == -102
CppyyTestData.s_short = -203
@@ -349,14 +456,14 @@ class AppTestDATATYPES:
assert CppyyTestData.s_uint == 4321
raises(ValueError, setattr, c, 's_uint', -1)
raises(ValueError, setattr, CppyyTestData, 's_uint', -1)
- CppyyTestData.s_long = -87
- assert c.s_long == -87
- c.s_long = 876
- assert CppyyTestData.s_long == 876
- CppyyTestData.s_ulong = 876
- assert c.s_ulong == 876
- c.s_ulong = 678
- assert CppyyTestData.s_ulong == 678
+ CppyyTestData.s_long = -pylong(87)
+ assert c.s_long == -pylong(87)
+ c.s_long = pylong(876)
+ assert CppyyTestData.s_long == pylong(876)
+ CppyyTestData.s_ulong = pylong(876)
+ assert c.s_ulong == pylong(876)
+ c.s_ulong = pylong(678)
+ assert CppyyTestData.s_ulong == pylong(678)
raises(ValueError, setattr, CppyyTestData, 's_ulong', -1)
raises(ValueError, setattr, c, 's_ulong', -1)
@@ -405,9 +512,9 @@ class AppTestDATATYPES:
c.m_double = -1
assert round(c.m_double + 1.0, 8) == 0
- raises(TypeError, c.m_double, 'c')
- raises(TypeError, c.m_int, -1.)
- raises(TypeError, c.m_int, 1.)
+ raises(TypeError, setattr, c.m_double, 'c')
+ raises(TypeError, setattr, c.m_int, -1.)
+ raises(TypeError, setattr, c.m_int, 1.)
c.__destruct__()
@@ -433,7 +540,8 @@ class AppTestDATATYPES:
import _cppyy as cppyy
gbl = cppyy.gbl
- raises(ReferenceError, 'gbl.g_pod.m_int')
+ with raises(ReferenceError):
+ gbl.g_pod.m_int
c = gbl.CppyyTestPod()
c.m_int = 42
@@ -722,13 +830,17 @@ class AppTestDATATYPES:
CppyyTestData = cppyy.gbl.CppyyTestData
c = CppyyTestData()
+ byte_array_names = []
+ if self.has_byte:
+ byte_array_names = ['get_byte_array', 'get_byte_array2']
for func in ['get_bool_array', 'get_bool_array2',
- 'get_uchar_array', 'get_uchar_array2',
+ 'get_uchar_array', 'get_uchar_array2',
'get_ushort_array', 'get_ushort_array2',
'get_int_array', 'get_int_array2',
'get_uint_array', 'get_uint_array2',
'get_long_array', 'get_long_array2',
- 'get_ulong_array', 'get_ulong_array2']:
+ 'get_ulong_array', 'get_ulong_array2']+\
+ byte_array_names:
arr = getattr(c, func)()
arr.reshape((self.N,))
assert len(arr) == self.N
@@ -791,7 +903,43 @@ class AppTestDATATYPES:
c.s_voidp = c2
address_equality_test(c.s_voidp, c2)
- def test21_function_pointers(self):
+ def test21_byte_arrays(self):
+ """Usage of unsigned char* as byte array and std::byte*"""
+
+ import _cppyy as cppyy
+ import array, ctypes
+
+ buf = b'123456789'
+ total = 0
+ for c in buf:
+ try:
+ total += ord(c) # p2
+ except TypeError:
+ total += c # p3
+
+ def run(self, f, buf, total):
+
+ # The following create a unique type for fixed-size C arrays: ctypes.c_char_Array_9
+ # and neither inherits from a non-sized type nor implements the buffer interface.
+ # As such, it can't be handled. TODO?
+ #pbuf = ctypes.create_string_buffer(len(buf), buf)
+ #assert f(pbuf, len(buf)) == total
+
+ pbuf = array.array('B', buf)
+ assert f(pbuf, len(buf)) == total
+
+ pbuf = (ctypes.c_ubyte * len(buf)).from_buffer_copy(buf)
+ assert f(pbuf, len(buf)) == total
+
+ pbuf = ctypes.cast(buf, ctypes.POINTER(ctypes.c_ubyte * len(buf)))[0]
+ assert f(pbuf, len(buf)) == total
+
+ run(self, cppyy.gbl.sum_uc_data, buf, total)
+
+ if self.has_byte:
+ run(self, cppyy.gbl.sum_byte_data, buf, total)
+
+ def test22_function_pointers(self):
"""Function pointer passing"""
import os
@@ -805,7 +953,7 @@ class AppTestDATATYPES:
import _cppyy as cppyy
- f1 = cppyy.gbl.sum_of_int
+ f1 = cppyy.gbl.sum_of_int1
f2 = cppyy.gbl.sum_of_double
f3 = cppyy.gbl.call_double_double
diff --git a/pypy/module/_cppyy/test/test_fragile.py b/pypy/module/_cppyy/test/test_fragile.py
index 1310420033..796b524daf 100644
--- a/pypy/module/_cppyy/test/test_fragile.py
+++ b/pypy/module/_cppyy/test/test_fragile.py
@@ -1,12 +1,12 @@
import py, os, sys
-from .support import setup_make
-
+from .support import setup_make, soext
currpath = py.path.local(__file__).dirpath()
-test_dct = str(currpath.join("fragileDict.so"))
+test_dct = str(currpath.join("fragileDict"))+soext
def setup_module(mod):
- setup_make("fragileDict.so")
+ setup_make("fragile")
+
class AppTestFRAGILE:
spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
@@ -21,12 +21,12 @@ class AppTestFRAGILE:
def test01_missing_classes(self):
"""Test (non-)access to missing classes"""
- import _cppyy
+ import _cppyy as cppyy
- raises(AttributeError, getattr, _cppyy.gbl, "no_such_class")
+ raises(AttributeError, getattr, cppyy.gbl, "no_such_class")
- assert _cppyy.gbl.fragile == _cppyy.gbl.fragile
- fragile = _cppyy.gbl.fragile
+ assert cppyy.gbl.fragile == cppyy.gbl.fragile
+ fragile = cppyy.gbl.fragile
raises(AttributeError, getattr, fragile, "no_such_class")
@@ -44,10 +44,10 @@ class AppTestFRAGILE:
def test02_arguments(self):
"""Test reporting when providing wrong arguments"""
- import _cppyy
+ import _cppyy as cppyy
- assert _cppyy.gbl.fragile == _cppyy.gbl.fragile
- fragile = _cppyy.gbl.fragile
+ assert cppyy.gbl.fragile == cppyy.gbl.fragile
+ fragile = cppyy.gbl.fragile
assert fragile.D == fragile.D
assert fragile.D().check() == ord('D')
@@ -62,10 +62,10 @@ class AppTestFRAGILE:
def test03_unsupported_arguments(self):
"""Test arguments that are yet unsupported"""
- import _cppyy
+ import _cppyy as cppyy
- assert _cppyy.gbl.fragile == _cppyy.gbl.fragile
- fragile = _cppyy.gbl.fragile
+ assert cppyy.gbl.fragile == cppyy.gbl.fragile
+ fragile = cppyy.gbl.fragile
assert fragile.E == fragile.E
assert fragile.E().check() == ord('E')
@@ -79,10 +79,10 @@ class AppTestFRAGILE:
def test04_wrong_arg_addressof(self):
"""Test addressof() error reporting"""
- import _cppyy
+ import _cppyy as cppyy
- assert _cppyy.gbl.fragile == _cppyy.gbl.fragile
- fragile = _cppyy.gbl.fragile
+ assert cppyy.gbl.fragile == cppyy.gbl.fragile
+ fragile = cppyy.gbl.fragile
assert fragile.F == fragile.F
assert fragile.F().check() == ord('F')
@@ -90,18 +90,18 @@ class AppTestFRAGILE:
f = fragile.F()
o = object()
- _cppyy.addressof(f)
- raises(TypeError, _cppyy.addressof, o)
- raises(TypeError, _cppyy.addressof, 1)
+ cppyy.addressof(f)
+ raises(TypeError, cppyy.addressof, o)
+ raises(TypeError, cppyy.addressof, 1)
# see also test08_void_pointer_passing in test_advancedcpp.py
def test05_wrong_this(self):
"""Test that using an incorrect self argument raises"""
- import _cppyy
+ import _cppyy as cppyy
- assert _cppyy.gbl.fragile == _cppyy.gbl.fragile
- fragile = _cppyy.gbl.fragile
+ assert cppyy.gbl.fragile == cppyy.gbl.fragile
+ fragile = cppyy.gbl.fragile
a = fragile.A()
assert fragile.A.check(a) == ord('A')
@@ -119,43 +119,43 @@ class AppTestFRAGILE:
def test06_unnamed_enum(self):
"""Test that an unnamed enum does not cause infinite recursion"""
- import _cppyy
+ import _cppyy as cppyy
- assert _cppyy.gbl.fragile is _cppyy.gbl.fragile
- fragile = _cppyy.gbl.fragile
- assert _cppyy.gbl.fragile is fragile
+ assert cppyy.gbl.fragile is cppyy.gbl.fragile
+ fragile = cppyy.gbl.fragile
+ assert cppyy.gbl.fragile is fragile
g = fragile.G()
def test07_unhandled_scoped_datamember(self):
"""Test that an unhandled scoped data member does not cause infinite recursion"""
- import _cppyy
+ import _cppyy as cppyy
- assert _cppyy.gbl.fragile is _cppyy.gbl.fragile
- fragile = _cppyy.gbl.fragile
- assert _cppyy.gbl.fragile is fragile
+ assert cppyy.gbl.fragile is cppyy.gbl.fragile
+ fragile = cppyy.gbl.fragile
+ assert cppyy.gbl.fragile is fragile
h = fragile.H()
def test08_operator_bool(self):
"""Access to global vars with an operator bool() returning False"""
- import _cppyy
+ import _cppyy as cppyy
- i = _cppyy.gbl.fragile.I()
+ i = cppyy.gbl.fragile.I()
assert not i
- g = _cppyy.gbl.fragile.gI
+ g = cppyy.gbl.fragile.gI
assert not g
def test09_documentation(self):
"""Check contents of documentation"""
- import _cppyy
+ import _cppyy as cppyy
- assert _cppyy.gbl.fragile == _cppyy.gbl.fragile
- fragile = _cppyy.gbl.fragile
+ assert cppyy.gbl.fragile == cppyy.gbl.fragile
+ fragile = cppyy.gbl.fragile
d = fragile.D()
try:
@@ -197,9 +197,9 @@ class AppTestFRAGILE:
def test10_dir(self):
"""Test __dir__ method"""
- import _cppyy
+ import _cppyy as cppyy
- members = dir(_cppyy.gbl.fragile)
+ members = dir(cppyy.gbl.fragile)
assert 'A' in members
assert 'B' in members
assert 'C' in members
@@ -215,7 +215,7 @@ class AppTestFRAGILE:
def test11_imports(self):
"""Test ability to import from namespace (or fail with ImportError)"""
- import _cppyy
+ import _cppyy as cppyy
# TODO: namespaces aren't loaded (and thus not added to sys.modules)
# with just the from ... import statement; actual use is needed
@@ -231,51 +231,51 @@ class AppTestFRAGILE:
raises(ImportError, fail_import)
from cppyy.gbl.fragile import A, B, C, D
- assert _cppyy.gbl.fragile.A is A
- assert _cppyy.gbl.fragile.B is B
- assert _cppyy.gbl.fragile.C is C
- assert _cppyy.gbl.fragile.D is D
+ assert cppyy.gbl.fragile.A is A
+ assert cppyy.gbl.fragile.B is B
+ assert cppyy.gbl.fragile.C is C
+ assert cppyy.gbl.fragile.D is D
# according to warnings, can't test "import *" ...
from cppyy.gbl.fragile import nested1
- assert _cppyy.gbl.fragile.nested1 is nested1
+ assert cppyy.gbl.fragile.nested1 is nested1
assert nested1.__name__ == 'nested1'
assert nested1.__module__ == 'cppyy.gbl.fragile'
- assert nested1.__cppname__ == 'fragile::nested1'
+ assert nested1.__cpp_name__ == 'fragile::nested1'
from cppyy.gbl.fragile.nested1 import A, nested2
- assert _cppyy.gbl.fragile.nested1.A is A
+ assert cppyy.gbl.fragile.nested1.A is A
assert A.__name__ == 'A'
assert A.__module__ == 'cppyy.gbl.fragile.nested1'
- assert A.__cppname__ == 'fragile::nested1::A'
- assert _cppyy.gbl.fragile.nested1.nested2 is nested2
+ assert A.__cpp_name__ == 'fragile::nested1::A'
+ assert cppyy.gbl.fragile.nested1.nested2 is nested2
assert A.__name__ == 'A'
assert A.__module__ == 'cppyy.gbl.fragile.nested1'
- assert nested2.__cppname__ == 'fragile::nested1::nested2'
+ assert nested2.__cpp_name__ == 'fragile::nested1::nested2'
from cppyy.gbl.fragile.nested1.nested2 import A, nested3
- assert _cppyy.gbl.fragile.nested1.nested2.A is A
+ assert cppyy.gbl.fragile.nested1.nested2.A is A
assert A.__name__ == 'A'
assert A.__module__ == 'cppyy.gbl.fragile.nested1.nested2'
- assert A.__cppname__ == 'fragile::nested1::nested2::A'
- assert _cppyy.gbl.fragile.nested1.nested2.nested3 is nested3
+ assert A.__cpp_name__ == 'fragile::nested1::nested2::A'
+ assert cppyy.gbl.fragile.nested1.nested2.nested3 is nested3
assert A.__name__ == 'A'
assert A.__module__ == 'cppyy.gbl.fragile.nested1.nested2'
- assert nested3.__cppname__ == 'fragile::nested1::nested2::nested3'
+ assert nested3.__cpp_name__ == 'fragile::nested1::nested2::nested3'
from cppyy.gbl.fragile.nested1.nested2.nested3 import A
- assert _cppyy.gbl.fragile.nested1.nested2.nested3.A is nested3.A
+ assert cppyy.gbl.fragile.nested1.nested2.nested3.A is nested3.A
assert A.__name__ == 'A'
assert A.__module__ == 'cppyy.gbl.fragile.nested1.nested2.nested3'
- assert A.__cppname__ == 'fragile::nested1::nested2::nested3::A'
+ assert A.__cpp_name__ == 'fragile::nested1::nested2::nested3::A'
def test12_missing_casts(self):
"""Test proper handling when a hierarchy is not fully available"""
- import _cppyy
+ import _cppyy as cppyy
- k = _cppyy.gbl.fragile.K()
+ k = cppyy.gbl.fragile.K()
assert k is k.GimeK(False)
assert k is not k.GimeK(True)
@@ -292,10 +292,10 @@ class AppTestFRAGILE:
return # don't bother; is fixed in cling-support
- import _cppyy
+ import _cppyy as cppyy
- M = _cppyy.gbl.fragile.M
- N = _cppyy.gbl.fragile.N
+ M = cppyy.gbl.fragile.M
+ N = cppyy.gbl.fragile.N
assert M.kOnce == N.kOnce
assert M.kTwice == N.kTwice
diff --git a/pypy/module/_cppyy/test/test_operators.py b/pypy/module/_cppyy/test/test_operators.py
index d3eac0dcec..c2959453bb 100644
--- a/pypy/module/_cppyy/test/test_operators.py
+++ b/pypy/module/_cppyy/test/test_operators.py
@@ -1,12 +1,12 @@
import py, os, sys
-from .support import setup_make
-
+from .support import setup_make, soext
currpath = py.path.local(__file__).dirpath()
-test_dct = str(currpath.join("operatorsDict.so"))
+test_dct = str(currpath.join("operatorsDict"))+soext
def setup_module(mod):
- setup_make("operatorsDict.so")
+ setup_make("operators")
+
class AppTestOPERATORS:
spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
@@ -26,8 +26,9 @@ class AppTestOPERATORS:
def test01_math_operators(self):
"""Test overloading of math operators"""
- import _cppyy
- number = _cppyy.gbl.number
+ import _cppyy as cppyy
+
+ number = cppyy.gbl.number
assert (number(20) + number(10)) == number(30)
assert (number(20) + 10 ) == number(30)
@@ -48,8 +49,9 @@ class AppTestOPERATORS:
def test02_unary_math_operators(self):
"""Test overloading of unary math operators"""
- import _cppyy
- number = _cppyy.gbl.number
+ import _cppyy as cppyy
+
+ number = cppyy.gbl.number
n = number(20)
n += number(10)
@@ -64,8 +66,9 @@ class AppTestOPERATORS:
def test03_comparison_operators(self):
"""Test overloading of comparison operators"""
- import _cppyy
- number = _cppyy.gbl.number
+ import _cppyy as cppyy
+
+ number = cppyy.gbl.number
assert (number(20) > number(10)) == True
assert (number(20) < number(10)) == False
@@ -77,8 +80,9 @@ class AppTestOPERATORS:
def test04_boolean_operator(self):
"""Test implementation of operator bool"""
- import _cppyy
- number = _cppyy.gbl.number
+ import _cppyy as cppyy
+
+ number = cppyy.gbl.number
n = number(20)
assert n
@@ -89,8 +93,15 @@ class AppTestOPERATORS:
def test05_exact_types(self):
"""Test converter operators of exact types"""
- import _cppyy
- gbl = _cppyy.gbl
+ import sys
+ import _cppyy as cppyy
+
+ if sys.hexversion >= 0x3000000:
+ pylong = int
+ else:
+ pylong = long
+
+ gbl = cppyy.gbl
o = gbl.operator_char_star()
assert o.m_str == 'operator_char_star'
@@ -105,8 +116,8 @@ class AppTestOPERATORS:
assert int(o) == -13
o = gbl.operator_long(); o.m_long = 42
- assert o.m_long == 42
- assert long(o) == 42
+ assert o.m_long == 42
+ assert pylong(o) == 42
o = gbl.operator_double(); o.m_double = 3.1415
assert o.m_double == 3.1415
@@ -115,21 +126,30 @@ class AppTestOPERATORS:
def test06_approximate_types(self):
"""Test converter operators of approximate types"""
- import _cppyy, sys
- gbl = _cppyy.gbl
+ import sys
+ import _cppyy as cppyy
+
+ if sys.hexversion >= 0x3000000:
+ pylong = int
+ maxvalue = sys.maxsize
+ else:
+ pylong = long
+ maxvalue = sys.maxint
+
+ gbl = cppyy.gbl
o = gbl.operator_short(); o.m_short = 256
assert o.m_short == 256
assert int(o) == 256
o = gbl.operator_unsigned_int(); o.m_uint = 2147483647 + 32
- assert o.m_uint == 2147483647 + 32
- assert long(o) == 2147483647 + 32
+ assert o.m_uint == 2147483647 + 32
+ assert pylong(o) == 2147483647 + 32
o = gbl.operator_unsigned_long();
- o.m_ulong = sys.maxint + 128
- assert o.m_ulong == sys.maxint + 128
- assert long(o) == sys.maxint + 128
+ o.m_ulong = maxvalue + 128
+ assert o.m_ulong == maxvalue + 128
+ assert pylong(o) == maxvalue + 128
o = gbl.operator_float(); o.m_float = 3.14
assert round(o.m_float - 3.14, 5) == 0.
@@ -138,12 +158,12 @@ class AppTestOPERATORS:
def test07_virtual_operator_eq(self):
"""Test use of virtual bool operator=="""
- import _cppyy
+ import _cppyy as cppyy
- b1 = _cppyy.gbl.v_opeq_base(1)
- b1a = _cppyy.gbl.v_opeq_base(1)
- b2 = _cppyy.gbl.v_opeq_base(2)
- b2a = _cppyy.gbl.v_opeq_base(2)
+ b1 = cppyy.gbl.v_opeq_base(1)
+ b1a = cppyy.gbl.v_opeq_base(1)
+ b2 = cppyy.gbl.v_opeq_base(2)
+ b2a = cppyy.gbl.v_opeq_base(2)
assert b1 == b1
assert b1 == b1a
@@ -152,10 +172,10 @@ class AppTestOPERATORS:
assert b2 == b2
assert b2 == b2a
- d1 = _cppyy.gbl.v_opeq_derived(1)
- d1a = _cppyy.gbl.v_opeq_derived(1)
- d2 = _cppyy.gbl.v_opeq_derived(2)
- d2a = _cppyy.gbl.v_opeq_derived(2)
+ d1 = cppyy.gbl.v_opeq_derived(1)
+ d1a = cppyy.gbl.v_opeq_derived(1)
+ d2 = cppyy.gbl.v_opeq_derived(2)
+ d2a = cppyy.gbl.v_opeq_derived(2)
# derived operator== returns opposite
assert not d1 == d1
diff --git a/pypy/module/_cppyy/test/test_pythonify.py b/pypy/module/_cppyy/test/test_pythonify.py
index d3bb5f6624..f7856258e3 100644
--- a/pypy/module/_cppyy/test/test_pythonify.py
+++ b/pypy/module/_cppyy/test/test_pythonify.py
@@ -1,14 +1,14 @@
import py, os, sys
-from .support import setup_make
+from .support import setup_make, soext
from pypy.module._cppyy import interp_cppyy, executor
-
currpath = py.path.local(__file__).dirpath()
-test_dct = str(currpath.join("example01Dict.so"))
+test_dct = str(currpath.join("example01Dict"))+soext
def setup_module(mod):
- setup_make("example01Dict.so")
+ setup_make("example01")
+
class AppTestPYTHONIFY:
spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
diff --git a/pypy/module/_cppyy/test/test_pythonization.py b/pypy/module/_cppyy/test/test_pythonization.py
index 7ef7a9df7b..14fecf18f5 100644
--- a/pypy/module/_cppyy/test/test_pythonization.py
+++ b/pypy/module/_cppyy/test/test_pythonization.py
@@ -1,13 +1,13 @@
import py, os, sys
from pytest import raises
-from .support import setup_make
-
+from .support import setup_make, soext
currpath = py.path.local(__file__).dirpath()
-test_dct = str(currpath.join("pythonizablesDict.so"))
+test_dct = str(currpath.join("pythonizablesDict"))+soext
def setup_module(mod):
- setup_make("pythonizablesDict.so")
+ setup_make("pythonizables")
+
class AppTestPYTHONIZATION:
spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
@@ -172,9 +172,9 @@ class AppTestPYTHONIZATION:
import _cppyy as cppyy
def root_pythonizor(klass, name):
- if name == 'TString':
+ if name == 'CppyyLegacy::TString':
klass.__len__ = klass.Length
cppyy.py.add_pythonization(root_pythonizor)
- assert len(cppyy.gbl.TString("aap")) == 3
+ assert len(cppyy.gbl.CppyyLegacy.TString("aap")) == 3
diff --git a/pypy/module/_cppyy/test/test_regression.py b/pypy/module/_cppyy/test/test_regression.py
index 21f82a4f31..70affb2c71 100644
--- a/pypy/module/_cppyy/test/test_regression.py
+++ b/pypy/module/_cppyy/test/test_regression.py
@@ -1,6 +1,4 @@
import py, os, sys
-from .support import setup_make
-
from pypy.module._cppyy import interp_cppyy, executor
diff --git a/pypy/module/_cppyy/test/test_stltypes.py b/pypy/module/_cppyy/test/test_stltypes.py
index 8ef0266fda..f4601f1b7c 100644
--- a/pypy/module/_cppyy/test/test_stltypes.py
+++ b/pypy/module/_cppyy/test/test_stltypes.py
@@ -1,12 +1,12 @@
import py, os, sys
-from .support import setup_make
-
+from .support import setup_make, soext
currpath = py.path.local(__file__).dirpath()
-test_dct = str(currpath.join("stltypesDict.so"))
+test_dct = str(currpath.join("stltypesDict"))+soext
def setup_module(mod):
- setup_make("stltypesDict.so")
+ setup_make("stltypes")
+
class AppTestSTLVECTOR:
spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
diff --git a/pypy/module/_cppyy/test/test_templates.py b/pypy/module/_cppyy/test/test_templates.py
index 48a4bff32e..3af808b58a 100644
--- a/pypy/module/_cppyy/test/test_templates.py
+++ b/pypy/module/_cppyy/test/test_templates.py
@@ -1,12 +1,12 @@
-import py, os, sys
-from .support import setup_make
-
+import py, os
+from .support import setup_make, soext
currpath = py.path.local(__file__).dirpath()
-test_dct = str(currpath.join("templatesDict.so"))
+test_dct = str(currpath.join("templatesDict"))+soext
def setup_module(mod):
- setup_make("templatesDict.so")
+ setup_make("templates")
+
class AppTestTEMPLATES:
spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
@@ -21,13 +21,13 @@ class AppTestTEMPLATES:
def test01_template_member_functions(self):
"""Template member functions lookup and calls"""
- import _cppyy
+ import _cppyy as cppyy
+ import sys
- m = _cppyy.gbl.MyTemplatedMethodClass()
+ m = cppyy.gbl.MyTemplatedMethodClass()
# implicit (called before other tests to check caching)
assert m.get_size(1) == m.get_int_size()+1
- assert 'get_size<int>' in dir(_cppyy.gbl.MyTemplatedMethodClass)
# pre-instantiated
assert m.get_size['char']() == m.get_char_size()
@@ -48,22 +48,20 @@ class AppTestTEMPLATES:
assert m.get_size[float]() == m.get_float_size()
assert m.get_size['double']() == m.get_double_size()
assert m.get_size['MyTemplatedMethodClass']() == m.get_self_size()
- assert 'get_size<MyTemplatedMethodClass>' in dir(_cppyy.gbl.MyTemplatedMethodClass)
# auto through typedef
assert m.get_size['MyTMCTypedef_t']() == m.get_self_size()
- assert 'get_size<MyTMCTypedef_t>' in dir(_cppyy.gbl.MyTemplatedMethodClass)
assert m.get_size['MyTemplatedMethodClass']() == m.get_self_size()
def test02_non_type_template_args(self):
"""Use of non-types as template arguments"""
- import _cppyy
+ import _cppyy as cppyy
- _cppyy.gbl.gInterpreter.Declare("template<int i> int nt_templ_args() { return i; };")
+ cppyy.gbl.gInterpreter.Declare("template<int i> int nt_templ_args() { return i; };")
- assert _cppyy.gbl.nt_templ_args[1]() == 1
- assert _cppyy.gbl.nt_templ_args[256]() == 256
+ assert cppyy.gbl.nt_templ_args[1]() == 1
+ assert cppyy.gbl.nt_templ_args[256]() == 256
def test03_templated_function(self):
"""Templated global and static functions lookup and calls"""
@@ -116,74 +114,76 @@ class AppTestTEMPLATES:
def test04_variadic_function(self):
"""Call a variadic function"""
- import _cppyy
+ import _cppyy as cppyy
+ std = cppyy.gbl.std
- s = _cppyy.gbl.std.ostringstream('(', _cppyy.gbl.std.ios_base.ate)
- # Fails; selects void* overload (?!)
+ s = std.ostringstream('(', std.ios_base.ate)
+ # Fails; wrong overload on PyPy, none on CPython
#s << "("
- _cppyy.gbl.SomeNS.tuplify(s, 1, 4., "aap")
+ cppyy.gbl.SomeNS.tuplify(s, 1, 4., "aap")
assert s.str() == "(1, 4, aap, NULL)"
- _cppyy.gbl.gInterpreter.Declare("""
+ cppyy.gbl.gInterpreter.Declare("""
template<typename... myTypes>
int test04_variadic_func() { return sizeof...(myTypes); }
""")
- assert _cppyy.gbl.test04_variadic_func['int', 'double', 'void*']() == 3
+ assert cppyy.gbl.test04_variadic_func['int', 'double', 'void*']() == 3
def test05_variadic_overload(self):
"""Call an overloaded variadic function"""
- import _cppyy
+ import _cppyy as cppyy
- assert _cppyy.gbl.isSomeInt(3.) == False
- assert _cppyy.gbl.isSomeInt(1) == True
- assert _cppyy.gbl.isSomeInt() == False
- assert _cppyy.gbl.isSomeInt(1, 2, 3) == False
+ assert cppyy.gbl.isSomeInt(3.) == False
+ assert cppyy.gbl.isSomeInt(1) == True
+ assert cppyy.gbl.isSomeInt() == False
+ assert cppyy.gbl.isSomeInt(1, 2, 3) == False
def test06_variadic_sfinae(self):
"""Attribute testing through SFINAE"""
- import _cppyy
- Obj1 = _cppyy.gbl.AttrTesting.Obj1
- Obj2 = _cppyy.gbl.AttrTesting.Obj2
- has_var1 = _cppyy.gbl.AttrTesting.has_var1
- call_has_var1 = _cppyy.gbl.AttrTesting.call_has_var1
-
- move = _cppyy.gbl.std.move
+ import _cppyy as cppyy
+ cppyy.gbl.AttrTesting # load
+ Obj1 = cppyy.gbl.AttrTesting.Obj1
+ Obj2 = cppyy.gbl.AttrTesting.Obj2
+ has_var1 = cppyy.gbl.AttrTesting.has_var1
+ call_has_var1 = cppyy.gbl.AttrTesting.call_has_var1
assert has_var1(Obj1()) == hasattr(Obj1(), 'var1')
assert has_var1(Obj2()) == hasattr(Obj2(), 'var1')
assert has_var1(3) == hasattr(3, 'var1')
assert has_var1("aap") == hasattr("aap", 'var1')
+ move = cppyy.gbl.std.move
+
assert call_has_var1(move(Obj1())) == True
assert call_has_var1(move(Obj2())) == False
def test07_type_deduction(self):
"""Traits/type deduction"""
- import _cppyy
- Obj1 = _cppyy.gbl.AttrTesting.Obj1
- Obj2 = _cppyy.gbl.AttrTesting.Obj2
- select_template_arg = _cppyy.gbl.AttrTesting.select_template_arg
+ import _cppyy as cppyy
+ cppyy.gbl.AttrTesting # load
+ select_template_arg = cppyy.gbl.AttrTesting.select_template_arg
+ Obj1 = cppyy.gbl.AttrTesting.Obj1
+ Obj2 = cppyy.gbl.AttrTesting.Obj2
- # assert select_template_arg[0, Obj1, Obj2].argument == Obj1
+ #assert select_template_arg[0, Obj1, Obj2].argument == Obj1
assert select_template_arg[1, Obj1, Obj2].argument == Obj2
raises(TypeError, select_template_arg.__getitem__, 2, Obj1, Obj2)
- # TODO, this doesn't work for builtin types as the 'argument'
- # typedef will not resolve to a class
- #assert select_template_arg[1, int, float].argument == float
+ # TODO: the following only results in a Cling compilation error
+ #assert select_template_arg[1, int, float].argument == float
def test08_using_of_static_data(self):
"""Derived class using static data of base"""
- import _cppyy
+ import _cppyy as cppyy
# TODO: the following should live in templates.h, but currently fails
# in TClass::GetListOfMethods()
- _cppyy.gbl.gInterpreter.Declare("""
+ cppyy.gbl.gInterpreter.Declare("""
template <typename T> struct BaseClassWithStatic {
static T const ref_value;
};
@@ -202,12 +202,10 @@ class AppTestTEMPLATES:
T m_value;
};""")
+ assert cppyy.gbl.BaseClassWithStatic["size_t"].ref_value == 42
- # TODO: the ref_value property is inaccessible (offset == -1)
- # assert _cppyy.gbl.BaseClassWithStatic["size_t"].ref_value == 42
-
- b1 = _cppyy.gbl.DerivedClassUsingStatic["size_t"]( 0)
- b2 = _cppyy.gbl.DerivedClassUsingStatic["size_t"](100)
+ b1 = cppyy.gbl.DerivedClassUsingStatic["size_t"]( 0)
+ b2 = cppyy.gbl.DerivedClassUsingStatic["size_t"](100)
# assert b1.ref_value == 42
assert b1.m_value == 0
@@ -215,61 +213,635 @@ class AppTestTEMPLATES:
# assert b2.ref_value == 42
assert b2.m_value == 42
+ def test09_templated_callable(self):
+ """Test that templated operator() translates to __call__"""
+
+ import _cppyy as cppyy
+
+ tc = cppyy.gbl.TemplatedCallable()
+
+ assert tc(5) == 5.
+
+ def test10_templated_hidding_methods(self):
+ """Test that base class methods are not considered when hidden"""
+
+ import _cppyy as cppyy
+
+ B = cppyy.gbl.TemplateHiding.Base
+ D = cppyy.gbl.TemplateHiding.Derived
+
+ assert B().callme(1) == 2
+ assert D().callme() == 2
+ assert D().callme(2) == 2
+
+ def test11_templated_ctor(self):
+ """Test templated constructors"""
+
+ import _cppyy as cppyy
+
+ cppyy.gbl.gInterpreter.Declare("""
+ template <typename T>
+ class RTTest_SomeClassWithTCtor {
+ public:
+ template<typename R>
+ RTTest_SomeClassWithTCtor(int n, R val) : m_double(n+val) {}
+ double m_double;
+ };
+
+ namespace RTTest_SomeNamespace {
+
+ template <typename T>
+ class RTTest_SomeClassWithTCtor {
+ public:
+ RTTest_SomeClassWithTCtor() : m_double(-1.) {}
+ template<typename R>
+ RTTest_SomeClassWithTCtor(int n, R val) : m_double(n+val) {}
+ double m_double;
+ };
+
+ }
+ """)
+
+ gbl = cppyy.gbl
+
+ assert round(gbl.RTTest_SomeClassWithTCtor[int](1, 3.1).m_double - 4.1, 8) == 0.
+
+ RTTest2 = gbl.RTTest_SomeNamespace.RTTest_SomeClassWithTCtor
+ assert round(RTTest2[int](1, 3.1).m_double - 4.1, 8) == 0.
+ assert round(RTTest2[int]().m_double + 1., 8) == 0.
+
+ def test12_template_aliases(self):
+ """Access to templates made available with 'using'"""
+
+ import _cppyy as cppyy
+
+ # through dictionary
+ davec = cppyy.gbl.DA_vector["float"]()
+ davec += range(10)
+ assert davec[5] == 5
+
+ # through interpreter
+ cppyy.gbl.gInterpreter.Declare("template<typename T> using IA_vector = std::vector<T>;")
+ iavec = cppyy.gbl.IA_vector["float"]()
+ iavec += range(10)
+ assert iavec[5] == 5
+
+ # with variadic template
+ if cppyy.gbl.gInterpreter.ProcessLine("__cplusplus;") > 201402:
+ assert cppyy.gbl.using_problem.matryoshka[int, 3].type
+ assert cppyy.gbl.using_problem.matryoshka[int, 3, 4].type
+ assert cppyy.gbl.using_problem.make_vector[int , 3]
+ assert cppyy.gbl.using_problem.make_vector[int , 3]().m_val == 3
+ assert cppyy.gbl.using_problem.make_vector[int , 4]().m_val == 4
+
+ def test13_using_templated_method(self):
+ """Access to base class templated methods through 'using'"""
+
+ import _cppyy as cppyy
+
+ b = cppyy.gbl.using_problem.Base[int]()
+ assert type(b.get3()) == int
+ assert b.get3() == 5
+ assert type(b.get3['double'](5)) == float
+ assert b.get3['double'](5) == 10.
+
+ d = cppyy.gbl.using_problem.Derived[int]()
+ #assert type(d.get1['double'](5)) == float
+ #assert d.get1['double'](5) == 10.
+
+ assert type(d.get2()) == int
+ assert d.get2() == 5
+
+ assert type(d.get3['double'](5)) == float
+ assert d.get3['double'](5) == 10.
+ assert type(d.get3()) == int
+ assert d.get3() == 5
+
+ def test14_templated_return_type(self):
+ """Use of a templated return type"""
+
+ import _cppyy as cppyy
+
+ cppyy.gbl.gInterpreter.Declare("""
+ struct RTTest_SomeStruct1 {};
+ template<class ...T> struct RTTest_TemplatedList {};
+ template<class ...T> auto rttest_make_tlist(T ... args) {
+ return RTTest_TemplatedList<T...>{};
+ }
+
+ namespace RTTest_SomeNamespace {
+ struct RTTest_SomeStruct2 {};
+ template<class ...T> struct RTTest_TemplatedList2 {};
+ }
+
+ template<class ...T> auto rttest_make_tlist2(T ... args) {
+ return RTTest_SomeNamespace::RTTest_TemplatedList2<T...>{};
+ }
+ """)
+
+ rttest_make_tlist = cppyy.gbl.rttest_make_tlist
+ rttest_make_tlist2 = cppyy.gbl.rttest_make_tlist2
+ RTTest_SomeNamespace = cppyy.gbl.RTTest_SomeNamespace
+ RTTest_SomeStruct1 = cppyy.gbl.RTTest_SomeStruct1
+
+ assert rttest_make_tlist(RTTest_SomeStruct1())
+ assert rttest_make_tlist(RTTest_SomeNamespace.RTTest_SomeStruct2())
+ assert rttest_make_tlist2(RTTest_SomeStruct1())
+ assert rttest_make_tlist2(RTTest_SomeNamespace.RTTest_SomeStruct2())
+
+ def test15_rvalue_templates(self):
+ """Use of a template with r-values; should accept builtin types"""
+
+ import _cppyy as cppyy
+
+ is_valid = cppyy.gbl.T_WithRValue.is_valid
+
+ # bit of regression testing
+ assert is_valid(3)
+ assert is_valid['int'](3) # used to crash
+
+ # actual method calls
+ assert is_valid[int](1)
+ assert not is_valid(0)
+ assert is_valid(1.)
+ assert not is_valid(0.)
+
+ def test16_variadic(self):
+ """Range of variadic templates"""
+
+ import _cppyy as cppyy
+
+ ns = cppyy.gbl.some_variadic
+
+ def get_tn(ns):
+ # helper to make all platforms look the same
+ tn = ns.gTypeName
+ tn = tn.replace(' ', '')
+ tn = tn.replace('class', '')
+ tn = tn.replace('__cdecl', '')
+ tn = tn.replace('__thiscall', '')
+ tn = tn.replace('__ptr64', '')
+ return tn
+
+ # templated class
+ a = ns.A['int', 'double']()
+ assert get_tn(ns) == "some_variadic::A<int,double>"
+
+ # static functions
+ a.sa(1, 1., 'a')
+ assert get_tn(ns).find("some_variadic::A<int,double>::void(int&&,double&&,std::") == 0
+ ns.A['char&', 'double*'].sa(1, 1., 'a')
+ assert get_tn(ns).find("some_variadic::A<char&,double*>::void(int&&,double&&,std::") == 0
+ ns.A['char&', 'double*'].sa_T['int'](1, 1., 'a')
+ assert get_tn(ns).find("some_variadic::A<char&,double*>::int(int&&,double&&,std::") == 0
+
+ # member functions
+ a.a(1, 1., 'a')
+ assert get_tn(ns).find("void(some_variadic::A<int,double>::*)(int&&,double&&,std::") == 0
+ a.a_T['int'](1, 1., 'a')
+ assert get_tn(ns).find("int(some_variadic::A<int,double>::*)(int&&,double&&,std::") == 0
+
+ # non-templated class
+ b = ns.B()
+ assert get_tn(ns) == "some_variadic::B"
+
+ # static functions
+ b.sb(1, 1., 'a')
+ assert get_tn(ns).find("some_variadic::B::void(int&&,double&&,std::") == 0
+ ns.B.sb(1, 1., 'a')
+ assert get_tn(ns).find("some_variadic::B::void(int&&,double&&,std::") == 0
+ ns.B.sb_T['int'](1, 1., 'a')
+ assert get_tn(ns).find("some_variadic::B::int(int&&,double&&,std::") == 0
+
+ # member functions
+ b.b(1, 1., 'a')
+ assert get_tn(ns).find("void(some_variadic::B::*)(int&&,double&&,std::") == 0
+ b.b_T['int'](1, 1., 'a')
+ assert get_tn(ns).find("int(some_variadic::B::*)(int&&,double&&,std::") == 0
+
+ def test17_empty_body(self):
+ """Use of templated function with empty body"""
+
+ import _cppyy as cppyy
+
+ f_T = cppyy.gbl.T_WithEmptyBody.some_empty
+
+ assert cppyy.gbl.T_WithEmptyBody.side_effect == "not set"
+ assert f_T[int]() is None
+ assert cppyy.gbl.T_WithEmptyBody.side_effect == "side effect"
+
+ def test18_greedy_overloads(self):
+ """void*/void** should not pre-empt template instantiations"""
+
+ import _cppyy as cppyy
+
+ ns = cppyy.gbl.T_WithGreedyOverloads
+
+ # check that void* does not mask template instantiations
+ g1 = ns.WithGreedy1()
+ assert g1.get_size(ns.SomeClass(), True) == -1
+ assert g1.get_size(ns.SomeClass()) == cppyy.sizeof(ns.SomeClass)
+
+ # check that void* does not mask template instantiations
+ g2 = ns.WithGreedy2()
+ assert g2.get_size(ns.SomeClass()) == cppyy.sizeof(ns.SomeClass)
+ assert g2.get_size(ns.SomeClass(), True) == -1
+
+ # check that unknown classes do not mask template instantiations
+ g3 = ns.WithGreedy3()
+ assert g3.get_size(ns.SomeClass()) == cppyy.sizeof(ns.SomeClass)
+ assert g3.get_size(cppyy.nullptr, True) == -1
+
+ def test19_templated_operator_add(self):
+ """Templated operator+ is ambiguous: either __pos__ or __add__"""
+
+ import _cppyy as cppyy
+ gbl = cppyy.gbl
+
+ cppyy.gbl.gInterpreter.Declare("""
+ namespace OperatorAddTest {
+ template <class V>
+ class CustomVec {
+ V fX;
+ public:
+ CustomVec() : fX(0) {}
+ CustomVec(const V & a) : fX(a) { }
+ V X() const { return fX; }
+ template <class fV> CustomVec operator + (const fV& v) {
+ CustomVec<V> u;
+ u.fX = fX + v.fX;
+ return u;
+ }
+ }; }
+ """)
+
+ c = gbl.OperatorAddTest.CustomVec['double'](5.3)
+ d = gbl.OperatorAddTest.CustomVec['int'](1)
+
+ q = c + d
+
+ assert round(q.X() - 6.3, 8) == 0.
+
+ def test20_templated_ctor_with_defaults(self):
+ """Templated constructor with defaults used to be ignored"""
+
+ import _cppyy as cppyy
+
+ cppyy.gbl.gInterpreter.Declare(r"""
+ namespace TemplatedCtor { class C {
+ public:
+ template <typename Integer, typename std::enable_if_t<std::is_integral_v<Integer>, int> = 0>
+ C(Integer) {}
+ C(const std::string&) {}
+ }; }
+ """)
+
+ assert cppyy.gbl.TemplatedCtor.C(0)
+
+ def test21_type_deduction_with_conversion(self):
+ """Template instantiation with [] -> std::vector conversion"""
+
+ import _cppyy as cppyy
+
+ cppyy.gbl.gInterpreter.Declare("""
+ namespace l2v {
+ struct Base {};
+ struct Derived : Base {};
+
+ int test1(const std::vector<Base*>& v) { return (int)v.size(); }
+
+ template <typename T>
+ int test2(const std::vector<Derived*>& v) { return (int)v.size(); }
+
+ template <typename T>
+ int test2a(std::vector<Derived*> v) { return v.size(); }
+
+ template <typename T>
+ int test3(const std::vector<Base*>& v) { return (int)v.size(); }
+ }""")
+
+ l2v = cppyy.gbl.l2v
+
+ d1 = l2v.Derived()
+
+ assert l2v.test1([d1]) == 1
+ assert l2v.test1([d1, d1]) == 2
+
+ assert l2v.test2[int]([d1]) == 1
+ assert l2v.test2[int]([d1, d1]) == 2
+
+ assert l2v.test2a[int]([d1]) == 1
+ assert l2v.test2a[int]([d1, d1]) == 2
+
+ assert l2v.test3[int]([d1]) == 1
+ assert l2v.test3[int]([d1, d1]) == 2
-class AppTestBOOSTANY:
+ def test22_type_deduction_of_proper_integer_size(self):
+ """Template type from integer arg should be big enough"""
+
+ import _cppyy as cppyy
+
+ cppyy.gbl.gInterpreter.Declare("template <typename T> T PassSomeInt(T t) { return t; }")
+
+ PassSomeInt = cppyy.gbl.PassSomeInt
+
+ for val in [1, 100000000000, -2**32, 2**32-1, 2**64-1 -2**63]:
+ assert val == PassSomeInt(val)
+
+ for val in [2**64, -2**63-1]:
+ raises(OverflowError, PassSomeInt, val)
+
+ def test23_overloaded_setitem(self):
+ """Template with overloaded non-templated and templated setitem"""
+
+ import _cppyy as cppyy
+
+ MyVec = cppyy.gbl.TemplateWithSetItem.MyVec
+
+ v = MyVec["float"](2)
+ v[0] = 1 # used to throw TypeError
+
+ def test24_stdfunction_templated_arguments(self):
+ """Use of std::function with templated arguments"""
+
+ import _cppyy as cppyy
+
+ def callback(x):
+ return sum(x)
+
+ cppyy.gbl.gInterpreter.Declare("""double callback_vector(
+ const std::function<double(std::vector<double>)>& callback, std::vector<double> x) {
+ return callback(x);
+ }""")
+
+ assert cppyy.gbl.std.function['double(std::vector<double>)']
+
+ assert cppyy.gbl.callback_vector(callback, [1, 2, 3]) == 6
+
+ cppyy.gbl.gInterpreter.Declare("""double wrap_callback_vector(
+ double (*callback)(std::vector<double>), std::vector<double> x) {
+ return callback_vector(callback, x);
+ }""")
+
+ assert cppyy.gbl.wrap_callback_vector(callback, [4, 5, 6]) == 15
+
+ assert cppyy.gbl.std.function['double(std::vector<double>)']
+
+ def test25_partial_templates(self):
+ """Deduction of types with partial templates"""
+
+ import _cppyy as cppyy
+
+ cppyy.gbl.gInterpreter.Declare("""\
+ template <typename A, typename B>
+ B partial_template_foo1(B b) { return b; }
+
+ template <typename A, typename B>
+ B partial_template_foo2(B b) { return b; }
+
+ namespace partial_template {
+ template <typename A, typename B>
+ B foo1(B b) { return b; }
+
+ template <typename A, typename B>
+ B foo2(B b) { return b; }
+ }
+ """)
+
+ ns = cppyy.gbl.partial_template
+
+ assert cppyy.gbl.partial_template_foo1['double', 'int'](17) == 17
+ assert cppyy.gbl.partial_template_foo1['double'](17) == 17
+
+ assert cppyy.gbl.partial_template_foo1['double'](17) == 17
+ assert cppyy.gbl.partial_template_foo1['double', 'int'](17) == 17
+
+ assert ns.foo1['double', 'int'](17) == 17
+ assert ns.foo1['double'](17) == 17
+
+ assert ns.foo2['double'](17) == 17
+ assert ns.foo2['double', 'int'](17) == 17
+
+ cppyy.gbl.gInterpreter.Declare("""\
+ template <typename A, typename... Other, typename B>
+ B partial_template_bar1(B b) { return b; }
+
+ template <typename A, typename... Other, typename B>
+ B partial_template_bar2(B b) { return b; }
+
+ namespace partial_template {
+ template <typename A, typename... Other, typename B>
+ B bar1(B b) { return b; }
+
+ template <typename A, typename... Other, typename B>
+ B bar2(B b) { return b; }
+ }""")
+
+ assert cppyy.gbl.partial_template_bar1['double','int'](17) == 17
+ assert cppyy.gbl.partial_template_bar1['double'](17) == 17
+
+ assert cppyy.gbl.partial_template_bar2['double'](17) == 17
+ assert cppyy.gbl.partial_template_bar2['double','int'](17) == 17
+
+ assert ns.bar1['double','int'](17) == 17
+ assert ns.bar1['double'](17) == 17
+
+ assert ns.bar2['double'](17) == 17
+ assert ns.bar2['double','int'](17) == 17
+
+ def test26_variadic_constructor(self):
+ """Use of variadic template function as contructor"""
+
+ import _cppyy as cppyy
+
+ cppyy.gbl.gInterpreter.Declare("""\
+ namespace VadiadicConstructor {
+ class Atom {
+ public:
+ using mass_type = double;
+
+ Atom() {}
+
+ template<typename... Args>
+ explicit Atom(const mass_type& mass_in, Args&&... args) :
+ Atom(std::forward<Args>(args)...) {
+ constexpr bool is_mass =
+ std::disjunction_v<std::is_same<std::decay_t<Args>, mass_type>...>;
+ static_assert(!is_mass, "Please only provide one mass");
+ mass() = mass_in;
+ }
+
+ mass_type& mass() noexcept {
+ return m_m;
+ }
+
+ mass_type m_m = 0.0;
+ }; }""")
+
+ ns = cppyy.gbl.VadiadicConstructor
+
+ a = ns.Atom(1567.0)
+ assert a.m_m == 1567.0
+
+ def test27_enum_in_constructor(self):
+ """Use of enums in template function as constructor"""
+
+ import _cppyy as cppyy
+
+ cppyy.gbl.gInterpreter.Declare("""\
+ namespace EnumConstructor {
+ struct ST {
+ enum TI { I32 };
+ };
+
+ struct FS {
+ enum R { EQ, NE, GT, GE, LT, LE };
+
+ template<typename T>
+ FS(const std::string&, const ST::TI, R, const T&e) {}
+ }; }""")
+
+ ns = cppyy.gbl.EnumConstructor
+
+ assert ns.FS('i', ns.ST.I32, ns.FS.EQ, 10)
+ assert ns.FS('i', ns.ST.TI.I32, ns.FS.R.EQ, 10)
+
+
+class AppTestTEMPLATED_TYPEDEFS:
spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
def setup_class(cls):
cls.w_test_dct = cls.space.newtext(test_dct)
cls.w_templates = cls.space.appexec([], """():
import ctypes, _cppyy
- _cppyy._post_import_startup()""")
+ _cppyy._post_import_startup()
+ return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
+
+ def test01_using(self):
+ """Test presence and validity of using typededs"""
+
+ import _cppyy as cppyy
+
+ tct = cppyy.gbl.TemplatedTypedefs.DerivedWithUsing
+ dum = cppyy.gbl.TemplatedTypedefs.SomeDummy
+
+ assert tct[int, dum, 4].vsize == 4
+ assert tct[int, dum, 8].vsize == 8
+
+ in_type = tct[int, dum, 4].in_type
+ assert 'in_type' in dir(tct[int, dum, 4])
+
+ assert in_type.__name__ == 'in_type'
+ assert in_type.__cpp_name__ == 'TemplatedTypedefs::DerivedWithUsing<int,TemplatedTypedefs::SomeDummy,4>::in_type'
+
+ in_type_tt = tct[int, dum, 4].in_type_tt
+ assert 'in_type_tt' in dir(tct[int, dum, 4])
+
+ assert in_type_tt.__name__ == 'in_type_tt'
+ assert in_type_tt.__cpp_name__ == 'TemplatedTypedefs::DerivedWithUsing<int,TemplatedTypedefs::SomeDummy,4>::in_type_tt'
+
+ def test02_mapped_type_as_internal(self):
+ """Test that mapped types can be used as builting"""
+
+ import _cppyy as cppyy
+ tct = cppyy.gbl.TemplatedTypedefs.DerivedWithUsing
+ dum = cppyy.gbl.TemplatedTypedefs.SomeDummy
+
+ for argname in ['short', 'unsigned short', 'int']:
+ in_type = tct[argname, dum, 4].in_type
+ assert issubclass(in_type, int)
+ assert in_type(13) == 13
+ assert 2*in_type(42) - 84 == 0
+
+ for argname in ['unsigned int', 'long', 'unsigned long']:# TODO: 'long long', 'unsigned long long'
+ in_type = tct[argname, dum, 4].in_type
+ assert issubclass(in_type, pylong)
+ assert in_type(13) == 13
+ assert 2*in_type(42) - 84 == 0
- def test01_any_class(self):
- """Usage of boost::any"""
+ for argname in ['float', 'double', 'long double']:
+ in_type = tct[argname, dum, 4].in_type
+ assert issubclass(in_type, float)
+ assert in_type(13) == 13.
+ assert 2*in_type(42) - 84. == 0.
- import _cppyy
+ raises(TypeError, tct.__getitem__, 'gibberish', dum, 4)
- if not _cppyy.gbl.gInterpreter.Declare('#include "boost/any.hpp"'):
- import warnings
- warnings.warn('skipping boost/any testing')
- return
+ def test03_mapped_type_as_template_arg(self):
+ """Test that mapped types can be used as template arguments"""
- assert _cppyy.gbl.boost
- assert _cppyy.gbl.boost.any
+ import _cppyy as cppyy
+
+ tct = cppyy.gbl.TemplatedTypedefs.DerivedWithUsing
+ dum = cppyy.gbl.TemplatedTypedefs.SomeDummy
+
+ in_type = tct['unsigned int', dum, 4].in_type
+ assert tct['unsigned int', dum, 4] is tct[in_type, dum, 4]
+
+ in_type = tct['long double', dum, 4].in_type
+ assert tct['long double', dum, 4] is tct[in_type, dum, 4]
+ assert tct['double', dum, 4] is not tct[in_type, dum, 4]
+
+ def test04_type_deduction(self):
+ """Usage of type reducer"""
+
+ import _cppyy as cppyy
+
+ cppyy.gbl.gInterpreter.Declare("""
+ template <typename T> struct DeductTest_Wrap {
+ static auto whatis(T t) { return t; }
+ };
+ """)
+
+ w = cppyy.gbl.DeductTest_Wrap[int]()
+ three = w.whatis(3)
+ assert three == 3
+
+ def test05_type_deduction_and_extern(self):
+ """Usage of type reducer with extern template"""
+
+ import _cppyy as cppyy
+ import sys
- std, boost = _cppyy.gbl.std, _cppyy.gbl.boost
+ cppyy.gbl.gInterpreter.Declare("""\
+ namespace FailedTypeDeducer {
- assert std.list[boost.any]
+ template<class T>
+ class A {
+ public:
+ T result() { return T{5}; }
+ };
+
+ extern template class A<int>;
+ }""")
- val = boost.any()
- # test both by-ref and by rvalue
- v = std.vector[int]()
- val.__assign__(v)
- val.__assign__(std.move(std.vector[int](range(100))))
+ if sys.platform != 'darwin': # feature disabled
+ assert cppyy.gbl.FailedTypeDeducer.A[int]().result() == 42
+ assert cppyy.gbl.FailedTypeDeducer.A['double']().result() == 5.
- _cppyy.gbl.gInterpreter.ProcessLine(
- "namespace _cppyy_internal { auto* stdvectid = &typeid(std::vector<int>); }")
+ # FailedTypeDeducer::B is defined in the templates.h header
+ assert cppyy.gbl.FailedTypeDeducer.B['double']().result() == 5.
+ assert cppyy.gbl.FailedTypeDeducer.B[int]().result() == 5
- assert val.type() == _cppyy.gbl._cppyy_internal.stdvectid
- extract = boost.any_cast[std.vector[int]](val)
- assert type(extract) is std.vector[int]
- assert len(extract) == 100
- extract += range(100)
- assert len(extract) == 200
+class AppTestTEMPLATE_TYPE_REDUCTION:
+ spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
+
+ def setup_class(cls):
+ cls.w_test_dct = cls.space.newtext(test_dct)
+ cls.w_templates = cls.space.appexec([], """():
+ import ctypes, _cppyy
+ _cppyy._post_import_startup()
+ return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
+
+ def test01_reduce_binary(self):
+ """Squash template expressions for binary operations (like in gmpxx)"""
+
+ import _cppyy as cppyy
- val.__assign__(std.move(extract)) # move forced
+ e1 = cppyy.gbl.TypeReduction.Expr[int]()
+ e2 = cppyy.gbl.TypeReduction.Expr[int]()
- # TODO: we hit boost::any_cast<int>(boost::any* operand) instead
- # of the reference version which raises
- boost.any_cast.__useffi__ = False
- try:
- # raises(Exception, boost.any_cast[int], val)
- assert not boost.any_cast[int](val)
- except Exception:
- # getting here is good, too ...
- pass
+ cppyy.py.add_type_reducer('TypeReduction::BinaryExpr<int>', 'TypeReduction::Expr<int>')
- extract = boost.any_cast[std.vector[int]](val)
- assert len(extract) == 200
+ assert type(e1+e2) == cppyy.gbl.TypeReduction.Expr[int]
diff --git a/pypy/module/_cppyy/test/test_zjit.py b/pypy/module/_cppyy/test/test_zjit.py
index 4604477554..7f55593bf9 100644
--- a/pypy/module/_cppyy/test/test_zjit.py
+++ b/pypy/module/_cppyy/test/test_zjit.py
@@ -1,5 +1,5 @@
import py, os, sys
-from .support import setup_make
+from .support import setup_make, soext
from rpython.jit.metainterp.test.support import LLJitMixin
from rpython.rlib.objectmodel import specialize, instantiate
@@ -33,12 +33,11 @@ def get_tlobj(self):
return self._tlobj
llinterp.LLInterpreter.get_tlobj = get_tlobj
-
currpath = py.path.local(__file__).dirpath()
-test_dct = str(currpath.join("example01Dict.so"))
+test_dct = str(currpath.join("example01Dict"))+soext
def setup_module(mod):
- setup_make("example01Dict.so")
+ setup_make("example01")
class FakeBase(W_Root):
@@ -57,10 +56,18 @@ class FakeFloat(FakeBase):
typename = "float"
def __init__(self, val):
self.val = val
+class FakeComplex(FakeBase):
+ typename = "complex"
+ def __init__(self, rval, ival):
+ self.obj = (rval, ival)
class FakeString(FakeBase):
typename = "str"
def __init__(self, val):
self.val = val
+class FakeUnicode(FakeBase):
+ typename = "unicode"
+ def __init__(self, val):
+ self.val = val
class FakeTuple(FakeBase):
typename = "tuple"
def __init__(self, val):
@@ -133,8 +140,11 @@ class FakeSpace(object):
self.w_AttributeError = FakeException(self, "AttributeError")
self.w_Exception = FakeException(self, "Exception")
+ self.w_ImportError = FakeException(self, "ImportError")
self.w_KeyError = FakeException(self, "KeyError")
+ self.w_LookupError = FakeException(self, "LookupError")
self.w_NotImplementedError = FakeException(self, "NotImplementedError")
+ self.w_OSError = FakeException(self, "OSError")
self.w_ReferenceError = FakeException(self, "ReferenceError")
self.w_RuntimeError = FakeException(self, "RuntimeError")
self.w_SystemError = FakeException(self, "SystemError")
@@ -176,6 +186,10 @@ class FakeSpace(object):
return FakeFloat(obj)
@specialize.argtype(1)
+ def newcomplex(self, rval, ival):
+ return FakeComplex(rval, ival)
+
+ @specialize.argtype(1)
def newbytes(self, obj):
return FakeString(obj)
@@ -194,6 +208,18 @@ class FakeSpace(object):
assert isinstance(w_obj, FakeFloat)
return w_obj.val
+ def newutf8(self, obj, sz):
+ return FakeUnicode(obj)
+
+ def unicode_from_object(self, w_obj):
+ if isinstance (w_obj, FakeUnicode):
+ return w_obj
+ return FakeUnicode(w_obj.utf8_w(self))
+
+ def utf8_len_w(self, w_obj):
+ assert isinstance(w_obj, FakeUnicode)
+ return w_obj.val, len(w_obj.val)
+
@specialize.arg(1)
def interp_w(self, RequiredClass, w_obj, can_be_None=False):
if can_be_None and w_obj is None:
@@ -208,6 +234,7 @@ class FakeSpace(object):
def exception_match(self, typ, sub):
return typ is sub
+ @specialize.argtype(1)
def is_none(self, w_obj):
return w_obj is None