Author: Wim Lavrijsen <[email protected]>
Branch: reflex-support
Changeset: r62916:faf90f3638ca
Date: 2013-04-01 14:35 -0700
http://bitbucket.org/pypy/pypy/changeset/faf90f3638ca/
Log: initial scaffolding to allow a loadable reflection library to
provide the capi (this includes a cleanup of cppyy startup)
diff --git a/pypy/module/cppyy/__init__.py b/pypy/module/cppyy/__init__.py
--- a/pypy/module/cppyy/__init__.py
+++ b/pypy/module/cppyy/__init__.py
@@ -20,7 +20,7 @@
}
appleveldefs = {
- 'gbl' : 'pythonify.gbl',
+ '_init_pythonify' : 'pythonify._init_pythonify',
'load_reflection_info' : 'pythonify.load_reflection_info',
'add_pythonization' : 'pythonify.add_pythonization',
}
@@ -33,3 +33,9 @@
# code generation is not, so give it a chance to run now
from pypy.module.cppyy import capi
capi.register_pythonizations(space)
+
+ def startup(self, space):
+ from pypy.module.cppyy import capi
+ capi.verify_backend(space) # may raise ImportError
+
+ space.call_method(space.wrap(self), '_init_pythonify')
diff --git a/pypy/module/cppyy/capi/__init__.py
b/pypy/module/cppyy/capi/builtin_capi.py
rename from pypy/module/cppyy/capi/__init__.py
rename to pypy/module/cppyy/capi/builtin_capi.py
--- a/pypy/module/cppyy/capi/__init__.py
+++ b/pypy/module/cppyy/capi/builtin_capi.py
@@ -34,6 +34,9 @@
C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP)
C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER)
+def verify_backend(space):
+ return True # by definition
+
def direct_ptradd(ptr, offset):
offset = rffi.cast(rffi.SIZE_T, offset)
jit.promote(offset)
@@ -52,7 +55,7 @@
[C_SCOPE], rffi.INT,
threadsafe=ts_reflect,
compilation_info=backend.eci)
-def c_num_scopes(cppscope):
+def c_num_scopes(space, cppscope):
return _c_num_scopes(cppscope.handle)
_c_scope_name = rffi.llexternal(
"cppyy_scope_name",
@@ -68,11 +71,13 @@
compilation_info=backend.eci)
def c_resolve_name(name):
return charp2str_free(_c_resolve_name(name))
-c_get_scope_opaque = rffi.llexternal(
+_c_get_scope_opaque = rffi.llexternal(
"cppyy_get_scope",
[rffi.CCHARP], C_SCOPE,
threadsafe=ts_reflect,
compilation_info=backend.eci)
+def c_get_scope_opaque(space, name):
+ return _c_get_scope_opaque(name)
c_get_template = rffi.llexternal(
"cppyy_get_template",
[rffi.CCHARP], C_TYPE,
@@ -83,7 +88,7 @@
[C_TYPE, C_OBJECT], C_TYPE,
threadsafe=ts_reflect,
compilation_info=backend.eci)
-def c_actual_class(cppclass, cppobj):
+def c_actual_class(space, cppclass, cppobj):
return _c_actual_class(cppclass.handle, cppobj)
# memory management ----------------------------------------------------------
@@ -282,6 +287,8 @@
if derived == base:
return 0
return _c_base_offset(derived.handle, base.handle, address, direction)
+def c_base_offset1(derived_h, base, address, direction):
+ return _c_base_offset(derived_h, base.handle, address, direction)
# method/function reflection information -------------------------------------
_c_num_methods = rffi.llexternal(
diff --git a/pypy/module/cppyy/capi/loadable_capi.py
b/pypy/module/cppyy/capi/loadable_capi.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/capi/loadable_capi.py
@@ -0,0 +1,590 @@
+import atexit
+
+from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rlib import jit, rdynload, objectmodel
+from rpython.tool import leakfinder
+
+from pypy.interpreter.error import OperationError
+
+from pypy.module._cffi_backend.libraryobj import W_Library
+from pypy.module._cffi_backend.ctypefunc import W_CTypeFunc
+from pypy.module._cffi_backend.newtype import new_primitive_type,
new_pointer_type
+from pypy.module._cffi_backend.cdataobj import W_CData
+
+
+import reflex_capi as backend
+#import cint_capi as backend
+
+def identify():
+ return 'loadable_capi'
+pythonize = backend.pythonize
+register_pythonizations = backend.register_pythonizations
+std_string_name = backend.std_string_name
+
+ts_reflect = backend.ts_reflect
+ts_call = backend.ts_call
+ts_memory = backend.ts_memory
+ts_helper = backend.ts_helper
+
+_C_OPAQUE_PTR = rffi.LONG
+_C_OPAQUE_NULL = lltype.nullptr(rffi.LONGP.TO)# ALT: _C_OPAQUE_PTR.TO
+
+C_SCOPE = _C_OPAQUE_PTR
+C_NULL_SCOPE = rffi.cast(C_SCOPE, _C_OPAQUE_NULL)
+
+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_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP)
+C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER)
+
+def direct_ptradd(ptr, offset):
+ offset = rffi.cast(rffi.SIZE_T, offset)
+ jit.promote(offset)
+ assert lltype.typeOf(ptr) == C_OBJECT
+ address = rffi.cast(rffi.CCHARP, ptr)
+ return rffi.cast(C_OBJECT, lltype.direct_ptradd(address, offset))
+
+def exchange_address(ptr, cif_descr, index):
+ return rffi.ptradd(ptr, cif_descr.exchange_args[index])
+
+c_load_dictionary = backend.c_load_dictionary
+
+class State(object):
+ def __init__(self, space):
+ self.library = None
+ self.capi_calls = {}
+
+ c_scope_s = 'long'
+ c_type_s = 'long'
+
+ self.capi_call_ifaces = {
+ 'num_scopes' : ([new_primitive_type(space, c_scope_s)],
+ new_primitive_type(space, 'int')),
+ 'scope_name' : ([new_primitive_type(space, c_scope_s),
new_primitive_type(space, 'int')],
+ new_pointer_type(space,
new_primitive_type(space, 'char'))),
+
+ 'get_scope' : ([new_pointer_type(space,
new_primitive_type(space, 'char'))],
+ new_primitive_type(space, c_scope_s)),
+
+ 'actual_class' : ([new_primitive_type(space, c_type_s),
new_primitive_type(space, c_scope_s)],
+ new_primitive_type(space, c_type_s)),
+ }
+
+def verify_backend(space):
+ state = space.fromcache(State)
+ try:
+ if state.library is None:
+ state.library = W_Library(space, 'rflxlib.so', rdynload.RTLD_LOCAL
| rdynload.RTLD_LAZY)
+ except Exception:
+ if objectmodel.we_are_translated():
+ raise OperationError(space.w_ImportError,
+ space.wrap("missing reflection module
rflxlib.so!"))
+ return False
+ return True
+
+def get_capi_call(space, name):
+ state = space.fromcache(State)
+ try:
+ return state.capi_calls[name]
+ except KeyError:
+ pass
+ try:
+ if state.library is None:
+ state.library = W_Library(space, 'rflxlib.so', rdynload.RTLD_LOCAL
| rdynload.RTLD_LAZY)
+ iface = state.capi_call_ifaces[name]
+ cfunc = W_CTypeFunc(space, iface[0], iface[1], False)
+ capi_call = state.library.load_function(cfunc, 'cppyy_'+name)
+ # TODO: there must be a better way to trick the leakfinder ...
+ if not objectmodel.we_are_translated():
+ leakfinder.remember_free(capi_call.ctype.cif_descr._obj0)
+ state.capi_calls[name] = capi_call
+ return capi_call
+ except Exception:
+ pass
+ return None
+
+
+# name to opaque C++ scope representation ------------------------------------
+def c_num_scopes(space, cppscope):
+ num_scopes = get_capi_call(space, 'num_scopes')
+ if num_scopes:
+ return space.int_w(num_scopes.call([space.wrap(cppscope.handle)]))
+ return 0
+_c_scope_name = rffi.llexternal(
+ "cppyy_scope_name",
+ [C_SCOPE, rffi.INT], rffi.CCHARP,
+ compilation_info = backend.eci)
+def c_scope_name(cppscope, iscope):
+ return charp2str_free(_c_scope_name(cppscope.handle, iscope))
+
+_c_resolve_name = rffi.llexternal(
+ "cppyy_resolve_name",
+ [rffi.CCHARP], rffi.CCHARP,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_resolve_name(name):
+ return charp2str_free(_c_resolve_name(name))
+def c_get_scope_opaque(space, name):
+ get_scope = get_capi_call(space, 'get_scope')
+ if get_scope:
+ return rffi.cast(C_SCOPE,
space.int_w(get_scope.call([space.wrap(name)])))
+ return rffi.cast(C_SCOPE, 0)
+
+c_get_template = rffi.llexternal(
+ "cppyy_get_template",
+ [rffi.CCHARP], C_TYPE,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_actual_class(space, cppclass, cppobj):
+ actual_class = get_capi_call(space, 'actual_class')
+ if actual_class:
+ return rffi.cast(C_TYPE, space.int_w(
+ actual_class.call([space.wrap(cppclass.handle),
space.wrap(cppobj)])))
+ return rffi.cast(C_TYPE, 0)
+
+# memory management ----------------------------------------------------------
+_c_allocate = rffi.llexternal(
+ "cppyy_allocate",
+ [C_TYPE], C_OBJECT,
+ threadsafe=ts_memory,
+ compilation_info=backend.eci)
+def c_allocate(cppclass):
+ return _c_allocate(cppclass.handle)
+_c_deallocate = rffi.llexternal(
+ "cppyy_deallocate",
+ [C_TYPE, C_OBJECT], lltype.Void,
+ threadsafe=ts_memory,
+ compilation_info=backend.eci)
+def c_deallocate(cppclass, cppobject):
+ _c_deallocate(cppclass.handle, cppobject)
+_c_destruct = rffi.llexternal(
+ "cppyy_destruct",
+ [C_TYPE, C_OBJECT], lltype.Void,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+def c_destruct(cppclass, cppobject):
+ _c_destruct(cppclass.handle, cppobject)
+
+# method/function dispatching ------------------------------------------------
+c_call_v = rffi.llexternal(
+ "cppyy_call_v",
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+c_call_b = rffi.llexternal(
+ "cppyy_call_b",
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+c_call_c = rffi.llexternal(
+ "cppyy_call_c",
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CHAR,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+c_call_h = rffi.llexternal(
+ "cppyy_call_h",
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.SHORT,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+c_call_i = rffi.llexternal(
+ "cppyy_call_i",
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+c_call_l = rffi.llexternal(
+ "cppyy_call_l",
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONG,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+c_call_ll = rffi.llexternal(
+ "cppyy_call_ll",
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGLONG,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+c_call_f = rffi.llexternal(
+ "cppyy_call_f",
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+c_call_d = rffi.llexternal(
+ "cppyy_call_d",
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+
+c_call_r = rffi.llexternal(
+ "cppyy_call_r",
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.VOIDP,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+c_call_s = rffi.llexternal(
+ "cppyy_call_s",
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+
+c_constructor = rffi.llexternal(
+ "cppyy_constructor",
+ [C_METHOD, C_TYPE, rffi.INT, rffi.VOIDP], C_OBJECT,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+_c_call_o = rffi.llexternal(
+ "cppyy_call_o",
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG,
+ threadsafe=ts_call,
+ compilation_info=backend.eci)
+def c_call_o(method, cppobj, nargs, args, cppclass):
+ return _c_call_o(method, cppobj, nargs, args, cppclass.handle)
+
+_c_get_methptr_getter = rffi.llexternal(
+ "cppyy_get_methptr_getter",
+ [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci,
+ elidable_function=True)
+def c_get_methptr_getter(cppscope, index):
+ return _c_get_methptr_getter(cppscope.handle, index)
+
+# handling of function argument buffer ---------------------------------------
+c_allocate_function_args = rffi.llexternal(
+ "cppyy_allocate_function_args",
+ [rffi.SIZE_T], rffi.VOIDP,
+ threadsafe=ts_memory,
+ compilation_info=backend.eci)
+c_deallocate_function_args = rffi.llexternal(
+ "cppyy_deallocate_function_args",
+ [rffi.VOIDP], lltype.Void,
+ threadsafe=ts_memory,
+ compilation_info=backend.eci)
+c_function_arg_sizeof = rffi.llexternal(
+ "cppyy_function_arg_sizeof",
+ [], rffi.SIZE_T,
+ threadsafe=ts_memory,
+ compilation_info=backend.eci,
+ elidable_function=True)
+c_function_arg_typeoffset = rffi.llexternal(
+ "cppyy_function_arg_typeoffset",
+ [], rffi.SIZE_T,
+ threadsafe=ts_memory,
+ compilation_info=backend.eci,
+ elidable_function=True)
+
+# scope reflection information -----------------------------------------------
+c_is_namespace = rffi.llexternal(
+ "cppyy_is_namespace",
+ [C_SCOPE], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+c_is_enum = rffi.llexternal(
+ "cppyy_is_enum",
+ [rffi.CCHARP], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+
+# type/class reflection information ------------------------------------------
+_c_final_name = rffi.llexternal(
+ "cppyy_final_name",
+ [C_TYPE], rffi.CCHARP,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_final_name(cpptype):
+ return charp2str_free(_c_final_name(cpptype))
+_c_scoped_final_name = rffi.llexternal(
+ "cppyy_scoped_final_name",
+ [C_TYPE], rffi.CCHARP,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_scoped_final_name(cpptype):
+ return charp2str_free(_c_scoped_final_name(cpptype))
+c_has_complex_hierarchy = rffi.llexternal(
+ "cppyy_has_complex_hierarchy",
+ [C_TYPE], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+_c_num_bases = rffi.llexternal(
+ "cppyy_num_bases",
+ [C_TYPE], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_num_bases(cppclass):
+ return _c_num_bases(cppclass.handle)
+_c_base_name = rffi.llexternal(
+ "cppyy_base_name",
+ [C_TYPE, rffi.INT], rffi.CCHARP,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_base_name(cppclass, base_index):
+ return charp2str_free(_c_base_name(cppclass.handle, base_index))
+_c_is_subtype = rffi.llexternal(
+ "cppyy_is_subtype",
+ [C_TYPE, C_TYPE], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci,
+ elidable_function=True)
[email protected]_promote()
+def c_is_subtype(derived, base):
+ if derived == base:
+ return 1
+ return _c_is_subtype(derived.handle, base.handle)
+
+_c_base_offset = rffi.llexternal(
+ "cppyy_base_offset",
+ [C_TYPE, C_TYPE, C_OBJECT, rffi.INT], rffi.SIZE_T,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci,
+ elidable_function=True)
[email protected]_promote()
+def c_base_offset(derived, base, address, direction):
+ if derived == base:
+ return 0
+ return _c_base_offset(derived.handle, base.handle, address, direction)
+def c_base_offset1(derived_h, base, address, direction):
+ return _c_base_offset(derived_h, base.handle, address, direction)
+
+# method/function reflection information -------------------------------------
+_c_num_methods = rffi.llexternal(
+ "cppyy_num_methods",
+ [C_SCOPE], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_num_methods(cppscope):
+ return _c_num_methods(cppscope.handle)
+_c_method_index_at = rffi.llexternal(
+ "cppyy_method_index_at",
+ [C_SCOPE, rffi.INT], C_INDEX,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_method_index_at(cppscope, imethod):
+ return _c_method_index_at(cppscope.handle, imethod)
+_c_method_indices_from_name = rffi.llexternal(
+ "cppyy_method_indices_from_name",
+ [C_SCOPE, rffi.CCHARP], C_INDEX_ARRAY,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_method_indices_from_name(cppscope, name):
+ indices = _c_method_indices_from_name(cppscope.handle, name)
+ if not indices:
+ return []
+ py_indices = []
+ i = 0
+ index = indices[i]
+ while index != -1:
+ i += 1
+ py_indices.append(index)
+ index = indices[i]
+ c_free(rffi.cast(rffi.VOIDP, indices)) # c_free defined below
+ return py_indices
+
+_c_method_name = rffi.llexternal(
+ "cppyy_method_name",
+ [C_SCOPE, C_INDEX], rffi.CCHARP,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_method_name(cppscope, index):
+ return charp2str_free(_c_method_name(cppscope.handle, index))
+_c_method_result_type = rffi.llexternal(
+ "cppyy_method_result_type",
+ [C_SCOPE, C_INDEX], rffi.CCHARP,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_method_result_type(cppscope, index):
+ return charp2str_free(_c_method_result_type(cppscope.handle, index))
+_c_method_num_args = rffi.llexternal(
+ "cppyy_method_num_args",
+ [C_SCOPE, C_INDEX], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_method_num_args(cppscope, index):
+ return _c_method_num_args(cppscope.handle, index)
+_c_method_req_args = rffi.llexternal(
+ "cppyy_method_req_args",
+ [C_SCOPE, C_INDEX], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_method_req_args(cppscope, index):
+ return _c_method_req_args(cppscope.handle, index)
+_c_method_arg_type = rffi.llexternal(
+ "cppyy_method_arg_type",
+ [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_method_arg_type(cppscope, index, arg_index):
+ return charp2str_free(_c_method_arg_type(cppscope.handle, index,
arg_index))
+_c_method_arg_default = rffi.llexternal(
+ "cppyy_method_arg_default",
+ [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_method_arg_default(cppscope, index, arg_index):
+ return charp2str_free(_c_method_arg_default(cppscope.handle, index,
arg_index))
+_c_method_signature = rffi.llexternal(
+ "cppyy_method_signature",
+ [C_SCOPE, C_INDEX], rffi.CCHARP,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_method_signature(cppscope, index):
+ return charp2str_free(_c_method_signature(cppscope.handle, index))
+
+_c_method_is_template = rffi.llexternal(
+ "cppyy_method_is_template",
+ [C_SCOPE, C_INDEX], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_method_is_template(cppscope, index):
+ return _c_method_is_template(cppscope.handle, index)
+_c_method_num_template_args = rffi.llexternal(
+ "cppyy_method_num_template_args",
+ [C_SCOPE, C_INDEX], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+_c_method_template_arg_name = rffi.llexternal(
+ "cppyy_method_template_arg_name",
+ [C_SCOPE, C_INDEX, C_INDEX], rffi.CCHARP,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_template_args(cppscope, index):
+ nargs = _c_method_num_template_args(cppscope.handle, index)
+ args = [c_resolve_name(
+ charp2str_free(_c_method_template_arg_name(cppscope.handle, index,
iarg)))
+ for iarg in range(nargs)]
+ return args
+
+_c_get_method = rffi.llexternal(
+ "cppyy_get_method",
+ [C_SCOPE, C_INDEX], C_METHOD,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_get_method(cppscope, index):
+ return _c_get_method(cppscope.handle, index)
+_c_get_global_operator = rffi.llexternal(
+ "cppyy_get_global_operator",
+ [C_SCOPE, C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_get_global_operator(nss, lc, rc, op):
+ if nss is not None:
+ return _c_get_global_operator(nss.handle, lc.handle, rc.handle, op)
+ return rffi.cast(WLAVC_INDEX, -1)
+
+# method properties ----------------------------------------------------------
+_c_is_constructor = rffi.llexternal(
+ "cppyy_is_constructor",
+ [C_TYPE, C_INDEX], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_is_constructor(cppclass, index):
+ return _c_is_constructor(cppclass.handle, index)
+_c_is_staticmethod = rffi.llexternal(
+ "cppyy_is_staticmethod",
+ [C_TYPE, C_INDEX], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_is_staticmethod(cppclass, index):
+ return _c_is_staticmethod(cppclass.handle, index)
+
+# data member reflection information -----------------------------------------
+_c_num_datamembers = rffi.llexternal(
+ "cppyy_num_datamembers",
+ [C_SCOPE], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_num_datamembers(cppscope):
+ return _c_num_datamembers(cppscope.handle)
+_c_datamember_name = rffi.llexternal(
+ "cppyy_datamember_name",
+ [C_SCOPE, rffi.INT], rffi.CCHARP,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_datamember_name(cppscope, datamember_index):
+ return charp2str_free(_c_datamember_name(cppscope.handle,
datamember_index))
+_c_datamember_type = rffi.llexternal(
+ "cppyy_datamember_type",
+ [C_SCOPE, rffi.INT], rffi.CCHARP,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_datamember_type(cppscope, datamember_index):
+ return charp2str_free(_c_datamember_type(cppscope.handle,
datamember_index))
+_c_datamember_offset = rffi.llexternal(
+ "cppyy_datamember_offset",
+ [C_SCOPE, rffi.INT], rffi.SIZE_T,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_datamember_offset(cppscope, datamember_index):
+ return _c_datamember_offset(cppscope.handle, datamember_index)
+
+_c_datamember_index = rffi.llexternal(
+ "cppyy_datamember_index",
+ [C_SCOPE, rffi.CCHARP], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_datamember_index(cppscope, name):
+ return _c_datamember_index(cppscope.handle, name)
+
+# data member properties -----------------------------------------------------
+_c_is_publicdata = rffi.llexternal(
+ "cppyy_is_publicdata",
+ [C_SCOPE, rffi.INT], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_is_publicdata(cppscope, datamember_index):
+ return _c_is_publicdata(cppscope.handle, datamember_index)
+_c_is_staticdata = rffi.llexternal(
+ "cppyy_is_staticdata",
+ [C_SCOPE, rffi.INT], rffi.INT,
+ threadsafe=ts_reflect,
+ compilation_info=backend.eci)
+def c_is_staticdata(cppscope, datamember_index):
+ return _c_is_staticdata(cppscope.handle, datamember_index)
+
+# misc helpers ---------------------------------------------------------------
+c_strtoll = rffi.llexternal(
+ "cppyy_strtoll",
+ [rffi.CCHARP], rffi.LONGLONG,
+ threadsafe=ts_helper,
+ compilation_info=backend.eci)
+c_strtoull = rffi.llexternal(
+ "cppyy_strtoull",
+ [rffi.CCHARP], rffi.ULONGLONG,
+ threadsafe=ts_helper,
+ compilation_info=backend.eci)
+c_free = rffi.llexternal(
+ "cppyy_free",
+ [rffi.VOIDP], lltype.Void,
+ threadsafe=ts_memory,
+ compilation_info=backend.eci)
+
+def charp2str_free(charp):
+ string = rffi.charp2str(charp)
+ voidp = rffi.cast(rffi.VOIDP, charp)
+ c_free(voidp)
+ return string
+
+c_charp2stdstring = rffi.llexternal(
+ "cppyy_charp2stdstring",
+ [rffi.CCHARP], C_OBJECT,
+ threadsafe=ts_helper,
+ compilation_info=backend.eci)
+c_stdstring2stdstring = rffi.llexternal(
+ "cppyy_stdstring2stdstring",
+ [C_OBJECT], C_OBJECT,
+ threadsafe=ts_helper,
+ compilation_info=backend.eci)
+c_assign2stdstring = rffi.llexternal(
+ "cppyy_assign2stdstring",
+ [C_OBJECT, rffi.CCHARP], lltype.Void,
+ threadsafe=ts_helper,
+ compilation_info=backend.eci)
+c_free_stdstring = rffi.llexternal(
+ "cppyy_free_stdstring",
+ [C_OBJECT], lltype.Void,
+ threadsafe=ts_helper,
+ compilation_info=backend.eci)
diff --git a/pypy/module/cppyy/interp_cppyy.py
b/pypy/module/cppyy/interp_cppyy.py
--- a/pypy/module/cppyy/interp_cppyy.py
+++ b/pypy/module/cppyy/interp_cppyy.py
@@ -58,7 +58,7 @@
except KeyError:
pass
- opaque_handle = capi.c_get_scope_opaque(true_name)
+ opaque_handle = capi.c_get_scope_opaque(space, true_name)
assert lltype.typeOf(opaque_handle) == capi.C_SCOPE
if opaque_handle:
final_name = capi.c_final_name(opaque_handle)
@@ -496,7 +496,7 @@
# The following code tries out each of the functions in order. If
# argument conversion fails (or simply if the number of arguments do
- # not match, that will lead to an exception, The JIT will snip out
+ # not match), that will lead to an exception, The JIT will snip out
# those (always) failing paths, but only if they have no side-effects.
# A second loop gathers all exceptions in the case all methods fail
# (the exception gathering would otherwise be a side-effect as far as
@@ -795,7 +795,7 @@
# The backend can filter by returning empty strings. Special care is
# taken for functions, which need not be unique (overloading).
alldir = []
- for i in range(capi.c_num_scopes(self)):
+ for i in range(capi.c_num_scopes(self.space, self)):
sname = capi.c_scope_name(self, i)
if sname: alldir.append(self.space.wrap(sname))
allmeth = {}
@@ -1139,11 +1139,11 @@
# cast to actual cast if requested and possible
w_pycppclass = space.w_None
if do_cast and rawobject:
- actual = capi.c_actual_class(cppclass, rawobject)
+ actual = capi.c_actual_class(space, cppclass, rawobject)
if actual != cppclass.handle:
try:
w_pycppclass = get_pythonized_cppclass(space, actual)
- offset = capi._c_base_offset(actual, cppclass.handle,
rawobject, -1)
+ offset = capi.c_base_offset1(actual, cppclass, rawobject, -1)
rawobject = capi.direct_ptradd(rawobject, offset)
w_cppclass = space.findattr(w_pycppclass,
space.wrap("_cpp_proxy"))
cppclass = space.interp_w(W_CPPClass, w_cppclass,
can_be_None=False)
diff --git a/pypy/module/cppyy/pythonify.py b/pypy/module/cppyy/pythonify.py
--- a/pypy/module/cppyy/pythonify.py
+++ b/pypy/module/cppyy/pythonify.py
@@ -1,5 +1,5 @@
# NOT_RPYTHON
-import cppyy
+# do not load cppyy here, see _init_pythonify()
import types, sys
@@ -22,12 +22,7 @@
class CppyyClassMeta(CppyyScopeMeta):
pass
-class CppyyClass(cppyy.CPPInstance):
- __metaclass__ = CppyyClassMeta
-
- def __init__(self, *args, **kwds):
- pass # ignored, for the C++ backend, ctor == __new__ + __init__
-
+# class CppyyClass defined in _init_pythonify()
class CppyyTemplateType(object):
def __init__(self, scope, name):
@@ -36,6 +31,7 @@
def _arg_to_str(self, arg):
if arg == str:
+ import cppyy
arg = cppyy._std_string_name()
elif type(arg) != str:
arg = arg.__name__
@@ -53,7 +49,7 @@
def clgen_callback(name):
return get_pycppclass(name)
-cppyy._set_class_generator(clgen_callback)
+
def make_static_function(func_name, cppol):
def function(*args):
@@ -81,6 +77,7 @@
else:
d = dict()
def cpp_proxy_loader(cls):
+ import cppyy
cpp_proxy = cppyy._scope_byname(cls.__name__ != '::' and
cls.__name__ or '')
del cls.__class__._cpp_proxy
cls._cpp_proxy = cpp_proxy
@@ -179,11 +176,13 @@
# its base class, resulting in the __set__() of its base class being
called
# by setattr(); so, store directly on the dictionary
pycppclass.__dict__[dm_name] = cppdm
- if cppyy._is_static(cppdm):
+ import cppyy
+ if cppyy._is_static(cppdm): # TODO: make this a method of cppdm
metacpp.__dict__[dm_name] = cppdm
# the call to register will add back-end specific pythonizations and thus
# needs to run first, so that the generic pythonizations can use them
+ import cppyy
cppyy._register_class(pycppclass)
_pythonize(pycppclass)
return pycppclass
@@ -193,6 +192,8 @@
def get_pycppitem(scope, name):
+ import cppyy
+
# resolve typedefs/aliases
full_name = (scope == gbl) and name or (scope.__name__+'::'+name)
true_name = cppyy._resolve_name(full_name)
@@ -232,7 +233,7 @@
try:
cppdm = scope._cpp_proxy.get_datamember(name)
setattr(scope, name, cppdm)
- if cppyy._is_static(cppdm):
+ if cppyy._is_static(cppdm): # TODO: make this a method of cppdm
setattr(scope.__class__, name, cppdm)
pycppitem = getattr(scope, name) # gets actual property value
except AttributeError:
@@ -301,6 +302,8 @@
# general note: use 'in pyclass.__dict__' rather than 'hasattr' to prevent
# adding pythonizations multiple times in derived classes
+ import cppyy
+
# map __eq__/__ne__ through a comparison to None
if '__eq__' in pyclass.__dict__:
def __eq__(self, other):
@@ -384,21 +387,44 @@
try:
return _loaded_dictionaries[name]
except KeyError:
+ import cppyy
lib = cppyy._load_dictionary(name)
_loaded_dictionaries[name] = lib
return lib
+def _init_pythonify():
+ # cppyy should not be loaded at the module level, as that will trigger a
+ # call to space.getbuiltinmodule(), which will cause cppyy to be loaded
+ # at pypy-c startup, rather than on the "import cppyy" statement
+ import cppyy
-# user interface objects (note the two-step of not calling scope_byname here:
-# creation of global functions may cause the creation of classes in the global
-# namespace, so gbl must exist at that point to cache them)
-gbl = make_cppnamespace(None, "::", None, False) # global C++ namespace
-gbl.__doc__ = "Global C++ namespace."
-sys.modules['cppyy.gbl'] = gbl
+ # top-level classes
+ global CppyyClass
+ class CppyyClass(cppyy.CPPInstance):
+ __metaclass__ = CppyyClassMeta
-# mostly for the benefit of the CINT backend, which treats std as special
-gbl.std = make_cppnamespace(None, "std", None, False)
-sys.modules['cppyy.gbl.std'] = gbl.std
+ def __init__(self, *args, **kwds):
+ pass # ignored, for the C++ backend, ctor == __new__ + __init__
+
+ # class generator callback
+ cppyy._set_class_generator(clgen_callback)
+
+ # user interface objects (note the two-step of not calling scope_byname
here:
+ # creation of global functions may cause the creation of classes in the
global
+ # namespace, so gbl must exist at that point to cache them)
+ global gbl
+ gbl = make_cppnamespace(None, "::", None, False) # global C++ namespace
+ gbl.__doc__ = "Global C++ namespace."
+
+ # mostly for the benefit of the CINT backend, which treats std as special
+ gbl.std = make_cppnamespace(None, "std", None, False)
+
+ # install for user access
+ cppyy.gbl = gbl
+
+ # install as modules to allow importing from
+ sys.modules['cppyy.gbl'] = gbl
+ sys.modules['cppyy.gbl.std'] = gbl.std
# user-defined pythonizations interface
_pythonizations = {}
diff --git a/pypy/module/cppyy/test/test_advancedcpp.py
b/pypy/module/cppyy/test/test_advancedcpp.py
--- a/pypy/module/cppyy/test/test_advancedcpp.py
+++ b/pypy/module/cppyy/test/test_advancedcpp.py
@@ -523,8 +523,9 @@
# wrong (clear from the generated code). Keep this test as it should
# be all better in the cling/llvm world ...
- if self.capi_identity == 'Reflex': # don't test anything
- return
+ # TODO: get the capi-identify test selection right ...
+ if self.capi_identity != 'CINT': # don't test anything for Reflex
+ return
import cppyy
diff --git a/pypy/module/cppyy/test/test_zjit.py
b/pypy/module/cppyy/test/test_zjit.py
--- a/pypy/module/cppyy/test/test_zjit.py
+++ b/pypy/module/cppyy/test/test_zjit.py
@@ -9,6 +9,8 @@
# These tests are for the backend that support the fast path only.
if capi.identify() == 'CINT':
py.test.skip("CINT does not support fast path")
+elif capi.identify() == 'loadable_capi':
+ py.test.skip("can not currently use FakeSpace with _cffi_backend")
# load cpyext early, or its global vars are counted as leaks in the test
# (note that the module is not otherwise used in the test itself)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit