def tf1_tf1(space, w_self, args_w): """Pythonized version of TF1 constructor: takes functions and callable objects, and allows a callback into them.""" from pypy.module.cppyy import interp_cppyy tf1_class = interp_cppyy.scope_byname(space, "TF1") # expected signature: # 1. (char* name, pyfunc, double xmin, double xmax, int npar = 0) argc = len(args_w) try: if argc < 4 or 5 < argc: raise TypeError("wrong number of arguments") # first argument must be a name funcname = space.str_w(args_w[0]) # last (optional) argument is number of parameters npar = 0 if argc == 5: npar = space.int_w(args_w[4]) # second argument must be a callable python object w_callable = args_w[1] if not space.is_true(space.callable(w_callable)): raise TypeError("2nd argument is not a valid python callable") # generate a pointer to function from pypy.module._cffi_backend import newtype, ctypefunc, func c_double = newtype.new_primitive_type(space, 'double') c_doublep = newtype.new_pointer_type(space, c_double) # wrap the callable as the signature needs modifying w_ifunc = interp_cppyy.get_interface_func(space, w_callable, npar) w_cfunc = ctypefunc.W_CTypeFunc(space, [c_doublep, c_doublep], c_double, False) w_callback = func.callback(space, w_cfunc, w_ifunc, None) funcaddr = rffi.cast(rffi.ULONG, w_callback.get_closure()) # so far, so good; leaves on issue: CINT is expecting a wrapper, but # we need the overload that takes a function pointer, which is not in # the dictionary, hence this helper: newinst = _create_tf1(space.str_w(args_w[0]), funcaddr, space.float_w(args_w[2]), space.float_w(args_w[3]), npar) # w_self is a null-ptr bound as TF1 from pypy.module.cppyy.interp_cppyy import W_CPPInstance, memory_regulator cppself = space.interp_w(W_CPPInstance, w_self, can_be_None=False) cppself._rawobject = newinst memory_regulator.register(cppself) # tie all the life times to the TF1 instance space.setattr(w_self, space.wrap('_callback'), w_callback) # by definition for __init__ return None except (OperationError, TypeError, IndexError), e: newargs_w = args_w[1:] # drop class
def get_primitive_type(ffi, num): space = ffi.space if not (0 <= num < cffi_opcode._NUM_PRIM): if num == cffi_opcode._UNKNOWN_PRIM: raise oefmt(ffi.w_FFIError, "primitive integer type with an " "unexpected size (or not an integer type at all)") elif num == cffi_opcode._UNKNOWN_FLOAT_PRIM: raise oefmt(ffi.w_FFIError, "primitive floating-point type with an " "unexpected size (or not a float type at all)") elif num == cffi_opcode._UNKNOWN_LONG_DOUBLE: raise oefmt(ffi.w_FFIError, "primitive floating-point type is " "'long double', not supported for now with " "the syntax 'typedef double... xxx;'") else: raise oefmt(space.w_NotImplementedError, "prim=%d", num) realize_cache = space.fromcache(RealizeCache) w_ctype = realize_cache.all_primitives[num] if w_ctype is None: if num == cffi_opcode.PRIM_VOID: w_ctype = newtype.new_void_type(space) else: assert RealizeCache.NAMES[num] w_ctype = newtype.new_primitive_type(space, RealizeCache.NAMES[num]) realize_cache.all_primitives[num] = w_ctype return w_ctype
def test_new_function_type_during_translation(self): space = self.space BInt = newtype.new_primitive_type(space, "int") BFunc = newtype.new_function_type(space, space.wrap([BInt]), BInt) assert BFunc is newtype.new_function_type(space,space.wrap([BInt]),BInt) unique_cache = space.fromcache(newtype.UniqueCache) unique_cache._cleanup_() assert BFunc is newtype.new_function_type(space,space.wrap([BInt]),BInt)
def get_primitive_type(ffi, num): space = ffi.space if not (0 <= num < cffi_opcode._NUM_PRIM): if num == cffi_opcode._UNKNOWN_PRIM: raise oefmt(ffi.w_FFIError, "primitive integer type with an " "unexpected size (or not an integer type at all)") else: raise oefmt(space.w_NotImplementedError, "prim=%d", num) realize_cache = space.fromcache(RealizeCache) w_ctype = realize_cache.all_primitives[num] if w_ctype is None: if num == cffi_opcode.PRIM_VOID: w_ctype = newtype.new_void_type(space) else: assert RealizeCache.NAMES[num] w_ctype = newtype.new_primitive_type(space, RealizeCache.NAMES[num]) realize_cache.all_primitives[num] = w_ctype return w_ctype
def __init__(self, space): self.library = None self.capi_calls = {} import pypy.module._cffi_backend.newtype as nt # 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 = nt.new_primitive_type(space, 'unsigned long') c_scope = c_opaque_ptr c_type = c_scope c_object = c_opaque_ptr c_method = c_opaque_ptr c_index = nt.new_primitive_type(space, 'long') c_void = nt.new_void_type(space) c_char = nt.new_primitive_type(space, 'char') c_uchar = nt.new_primitive_type(space, 'unsigned char') c_short = nt.new_primitive_type(space, 'short') c_int = nt.new_primitive_type(space, 'int') c_long = nt.new_primitive_type(space, 'long') c_llong = nt.new_primitive_type(space, 'long long') c_ullong = nt.new_primitive_type(space, 'unsigned long long') c_float = nt.new_primitive_type(space, 'float') c_double = nt.new_primitive_type(space, 'double') c_ccharp = nt.new_pointer_type(space, c_char) c_index_array = nt.new_pointer_type(space, c_void) c_voidp = nt.new_pointer_type(space, c_void) c_size_t = nt.new_primitive_type(space, 'size_t') c_ptrdiff_t = nt.new_primitive_type(space, 'ptrdiff_t') self.capi_call_ifaces = { # name to opaque C++ scope representation 'num_scopes' : ([c_scope], c_int), 'scope_name' : ([c_scope, c_int], c_ccharp), 'resolve_name' : ([c_ccharp], c_ccharp), 'get_scope' : ([c_ccharp], c_scope), 'get_template' : ([c_ccharp], c_type), 'actual_class' : ([c_type, c_object], c_type), # memory management 'allocate' : ([c_type], c_object), 'deallocate' : ([c_type, c_object], c_void), 'destruct' : ([c_type, c_object], c_void), # method/function dispatching 'call_v' : ([c_method, c_object, c_int, c_voidp], c_void), 'call_b' : ([c_method, c_object, c_int, c_voidp], c_uchar), 'call_c' : ([c_method, c_object, c_int, c_voidp], c_char), 'call_h' : ([c_method, c_object, c_int, c_voidp], c_short), 'call_i' : ([c_method, c_object, c_int, c_voidp], c_int), 'call_l' : ([c_method, c_object, c_int, c_voidp], c_long), 'call_ll' : ([c_method, c_object, c_int, c_voidp], c_llong), 'call_f' : ([c_method, c_object, c_int, c_voidp], c_float), 'call_d' : ([c_method, c_object, c_int, c_voidp], c_double), 'call_r' : ([c_method, c_object, c_int, c_voidp], c_voidp), 'call_s' : ([c_method, c_object, c_int, c_voidp], c_ccharp), 'constructor' : ([c_method, c_object, c_int, c_voidp], c_object), 'call_o' : ([c_method, c_object, c_int, c_voidp, c_type], c_object), 'get_methptr_getter' : ([c_scope, c_index], c_voidp), # TODO: verify # handling of function argument buffer 'allocate_function_args' : ([c_int], c_voidp), 'deallocate_function_args' : ([c_voidp], c_void), 'function_arg_sizeof' : ([], c_size_t), 'function_arg_typeoffset' : ([], c_size_t), # scope reflection information 'is_namespace' : ([c_scope], c_int), 'is_enum' : ([c_ccharp], c_int), # type/class reflection information 'final_name' : ([c_type], c_ccharp), 'scoped_final_name' : ([c_type], c_ccharp), 'has_complex_hierarchy' : ([c_type], c_int), 'num_bases' : ([c_type], c_int), 'base_name' : ([c_type, c_int], c_ccharp), 'is_subtype' : ([c_type, c_type], c_int), 'base_offset' : ([c_type, c_type, c_object, c_int], c_ptrdiff_t), # method/function reflection information 'num_methods' : ([c_scope], c_int), 'method_index_at' : ([c_scope, c_int], c_index), 'method_indices_from_name' : ([c_scope, c_ccharp], c_index_array), 'method_name' : ([c_scope, c_index], c_ccharp), 'method_result_type' : ([c_scope, c_index], c_ccharp), 'method_num_args' : ([c_scope, c_index], c_int), 'method_req_args' : ([c_scope, c_index], c_int), 'method_arg_type' : ([c_scope, c_index, c_int], c_ccharp), 'method_arg_default' : ([c_scope, c_index, c_int], c_ccharp), 'method_signature' : ([c_scope, c_index], c_ccharp), 'method_is_template' : ([c_scope, c_index], c_int), 'method_num_template_args' : ([c_scope, c_index], c_int), 'method_template_arg_name' : ([c_scope, c_index, c_index], c_ccharp), 'get_method' : ([c_scope, c_index], c_method), 'get_global_operator' : ([c_scope, c_scope, c_scope, c_ccharp], c_index), # method properties 'is_constructor' : ([c_type, c_index], c_int), 'is_staticmethod' : ([c_type, c_index], c_int), # data member reflection information 'num_datamembers' : ([c_scope], c_int), 'datamember_name' : ([c_scope, c_int], c_ccharp), 'datamember_type' : ([c_scope, c_int], c_ccharp), 'datamember_offset' : ([c_scope, c_int], c_ptrdiff_t), 'datamember_index' : ([c_scope, c_ccharp], c_int), # data member properties 'is_publicdata' : ([c_scope, c_int], c_int), 'is_staticdata' : ([c_scope, c_int], c_int), # misc helpers 'strtoll' : ([c_ccharp], c_llong), 'strtoull' : ([c_ccharp], c_ullong), 'free' : ([c_voidp], c_void), 'charp2stdstring' : ([c_ccharp], c_object), 'stdstring2stdstring' : ([c_object], c_object), } # size/offset are backend-specific but fixed after load self.c_sizeof_farg = 0 self.c_offset_farg = 0
def get_vararg_type(self): from pypy.module._cffi_backend import newtype return newtype.new_primitive_type(self.space, "int")
def get_vararg_type(self): if self.size < rffi.sizeof(rffi.INT): from pypy.module._cffi_backend import newtype return newtype.new_primitive_type(self.space, "int") return self
def __init__(self, space): self.library = None self.capi_calls = {} import pypy.module._cffi_backend.newtype as nt # 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 = nt.new_primitive_type(space, 'unsigned long') c_scope = c_opaque_ptr c_type = c_scope c_object = c_opaque_ptr c_method = c_opaque_ptr c_index = nt.new_primitive_type(space, 'long') c_void = nt.new_void_type(space) c_char = nt.new_primitive_type(space, 'char') c_uchar = nt.new_primitive_type(space, 'unsigned char') c_short = nt.new_primitive_type(space, 'short') c_int = nt.new_primitive_type(space, 'int') c_long = nt.new_primitive_type(space, 'long') c_llong = nt.new_primitive_type(space, 'long long') c_ullong = nt.new_primitive_type(space, 'unsigned long long') c_float = nt.new_primitive_type(space, 'float') c_double = nt.new_primitive_type(space, 'double') c_ccharp = nt.new_pointer_type(space, c_char) c_index_array = nt.new_pointer_type(space, c_void) c_voidp = nt.new_pointer_type(space, c_void) c_size_t = nt.new_primitive_type(space, 'size_t') c_ptrdiff_t = nt.new_primitive_type(space, 'ptrdiff_t') self.capi_call_ifaces = { # name to opaque C++ scope representation 'num_scopes': ([c_scope], c_int), 'scope_name': ([c_scope, c_int], c_ccharp), 'resolve_name': ([c_ccharp], c_ccharp), 'get_scope': ([c_ccharp], c_scope), 'get_template': ([c_ccharp], c_type), 'actual_class': ([c_type, c_object], c_type), # memory management 'allocate': ([c_type], c_object), 'deallocate': ([c_type, c_object], c_void), 'destruct': ([c_type, c_object], c_void), # method/function dispatching 'call_v': ([c_method, c_object, c_int, c_voidp], c_void), 'call_b': ([c_method, c_object, c_int, c_voidp], c_uchar), 'call_c': ([c_method, c_object, c_int, c_voidp], c_char), 'call_h': ([c_method, c_object, c_int, c_voidp], c_short), 'call_i': ([c_method, c_object, c_int, c_voidp], c_int), 'call_l': ([c_method, c_object, c_int, c_voidp], c_long), 'call_ll': ([c_method, c_object, c_int, c_voidp], c_llong), 'call_f': ([c_method, c_object, c_int, c_voidp], c_float), 'call_d': ([c_method, c_object, c_int, c_voidp], c_double), 'call_r': ([c_method, c_object, c_int, c_voidp], c_voidp), 'call_s': ([c_method, c_object, c_int, c_voidp], c_ccharp), 'constructor': ([c_method, c_object, c_int, c_voidp], c_object), 'call_o': ([c_method, c_object, c_int, c_voidp, c_type], c_object), 'get_methptr_getter': ([c_scope, c_index], c_voidp), # TODO: verify # handling of function argument buffer 'allocate_function_args': ([c_int], c_voidp), 'deallocate_function_args': ([c_voidp], c_void), 'function_arg_sizeof': ([], c_size_t), 'function_arg_typeoffset': ([], c_size_t), # scope reflection information 'is_namespace': ([c_scope], c_int), 'is_enum': ([c_ccharp], c_int), # type/class reflection information 'final_name': ([c_type], c_ccharp), 'scoped_final_name': ([c_type], c_ccharp), 'has_complex_hierarchy': ([c_type], c_int), 'num_bases': ([c_type], c_int), 'base_name': ([c_type, c_int], c_ccharp), 'is_subtype': ([c_type, c_type], c_int), 'base_offset': ([c_type, c_type, c_object, c_int], c_ptrdiff_t), # method/function reflection information 'num_methods': ([c_scope], c_int), 'method_index_at': ([c_scope, c_int], c_index), 'method_indices_from_name': ([c_scope, c_ccharp], c_index_array), 'method_name': ([c_scope, c_index], c_ccharp), 'method_result_type': ([c_scope, c_index], c_ccharp), 'method_num_args': ([c_scope, c_index], c_int), 'method_req_args': ([c_scope, c_index], c_int), 'method_arg_type': ([c_scope, c_index, c_int], c_ccharp), 'method_arg_default': ([c_scope, c_index, c_int], c_ccharp), 'method_signature': ([c_scope, c_index], c_ccharp), 'method_is_template': ([c_scope, c_index], c_int), 'method_num_template_args': ([c_scope, c_index], c_int), 'method_template_arg_name': ([c_scope, c_index, c_index], c_ccharp), 'get_method': ([c_scope, c_index], c_method), 'get_global_operator': ([c_scope, c_scope, c_scope, c_ccharp], c_index), # method properties 'is_constructor': ([c_type, c_index], c_int), 'is_staticmethod': ([c_type, c_index], c_int), # data member reflection information 'num_datamembers': ([c_scope], c_int), 'datamember_name': ([c_scope, c_int], c_ccharp), 'datamember_type': ([c_scope, c_int], c_ccharp), 'datamember_offset': ([c_scope, c_int], c_ptrdiff_t), 'datamember_index': ([c_scope, c_ccharp], c_int), # data member properties 'is_publicdata': ([c_scope, c_int], c_int), 'is_staticdata': ([c_scope, c_int], c_int), # misc helpers 'strtoll': ([c_ccharp], c_llong), 'strtoull': ([c_ccharp], c_ullong), 'free': ([c_voidp], c_void), 'charp2stdstring': ([c_ccharp], c_object), 'stdstring2stdstring': ([c_object], c_object), } # size/offset are backend-specific but fixed after load self.c_sizeof_farg = 0 self.c_offset_farg = 0
def ttree_getattr(space, w_self, args_w): """Specialized __getattr__ for TTree's that allows switching on/off the reading of individual branchs.""" from pypy.module.cppyy import interp_cppyy tree = space.interp_w(interp_cppyy.W_CPPInstance, w_self) space = tree.space # holds the class cache in State # prevent recursion attr = space.str_w(args_w[0]) if attr and attr[0] == '_': raise OperationError(space.w_AttributeError, args_w[0]) # try the saved cdata (for builtin types) try: w_cdata = space.getattr(w_self, space.wrap('_' + attr)) from pypy.module._cffi_backend import cdataobj cdata = space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False) return cdata.convert_to_object() except OperationError: pass # setup branch as a data member and enable it for reading w_branch = space.call_method(w_self, "GetBranch", args_w[0]) if not space.is_true(w_branch): raise OperationError(space.w_AttributeError, args_w[0]) activate_branch(space, w_branch) # figure out from where we're reading entry = space.r_longlong_w(space.call_method(w_self, "GetReadEntry")) if entry == -1: entry = 0 # setup cache structure w_klassname = space.call_method(w_branch, "GetClassName") if space.is_true(w_klassname): # some instance klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname)) w_obj = klass.construct() # 0x10000 = kDeleteObject; reset because we own the object space.call_method(w_branch, "ResetBit", space.wrap(0x10000)) space.call_method(w_branch, "SetObject", w_obj) space.call_method(w_branch, "GetEntry", space.wrap(entry)) space.setattr(w_self, args_w[0], w_obj) return w_obj else: # builtin data w_leaf = space.call_method(w_self, "GetLeaf", args_w[0]) space.call_method(w_branch, "GetEntry", space.wrap(entry)) # location w_address = space.call_method(w_leaf, "GetValuePointer") buf = space.getarg_w('s*', w_address) from pypy.module._rawffi import buffer assert isinstance(buf, buffer.RawFFIBuffer) address = rffi.cast(rffi.CCHARP, buf.datainstance.ll_buffer) # placeholder w_typename = space.call_method(w_leaf, "GetTypeName") from pypy.module.cppyy import capi typename = capi.c_resolve_name(space, space.str_w(w_typename)) if typename == 'bool': typename = '_Bool' w_address = space.call_method(w_leaf, "GetValuePointer") from pypy.module._cffi_backend import cdataobj, newtype cdata = cdataobj.W_CData(space, address, newtype.new_primitive_type(space, typename)) # cache result space.setattr(w_self, space.wrap('_' + attr), space.wrap(cdata)) return space.getattr(w_self, args_w[0])
def ttree_getattr(space, w_self, args_w): """Specialized __getattr__ for TTree's that allows switching on/off the reading of individual branchs.""" from pypy.module.cppyy import interp_cppyy tree = space.interp_w(interp_cppyy.W_CPPInstance, w_self) space = tree.space # holds the class cache in State # prevent recursion attr = space.str_w(args_w[0]) if attr and attr[0] == '_': raise OperationError(space.w_AttributeError, args_w[0]) # try the saved cdata (for builtin types) try: w_cdata = space.getattr(w_self, space.wrap('_'+attr)) from pypy.module._cffi_backend import cdataobj cdata = space.interp_w(cdataobj.W_CData, w_cdata, can_be_None=False) return cdata.convert_to_object() except OperationError: pass # setup branch as a data member and enable it for reading w_branch = space.call_method(w_self, "GetBranch", args_w[0]) if not space.is_true(w_branch): raise OperationError(space.w_AttributeError, args_w[0]) activate_branch(space, w_branch) # figure out from where we're reading entry = space.int_w(space.call_method(w_self, "GetReadEntry")) if entry == -1: entry = 0 # setup cache structure w_klassname = space.call_method(w_branch, "GetClassName") if space.is_true(w_klassname): # some instance klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname)) w_obj = klass.construct() space.call_method(w_branch, "SetObject", w_obj) space.call_method(w_branch, "GetEntry", space.wrap(entry)) space.setattr(w_self, args_w[0], w_obj) return w_obj else: # builtin data w_leaf = space.call_method(w_self, "GetLeaf", args_w[0]) space.call_method(w_branch, "GetEntry", space.wrap(entry)) # location w_address = space.call_method(w_leaf, "GetValuePointer") buf = space.buffer_w(w_address) from pypy.module._rawffi import buffer assert isinstance(buf, buffer.RawFFIBuffer) address = rffi.cast(rffi.CCHARP, buf.datainstance.ll_buffer) # placeholder w_typename = space.call_method(w_leaf, "GetTypeName" ) from pypy.module.cppyy import capi typename = capi.c_resolve_name(space, space.str_w(w_typename)) if typename == 'bool': typename = '_Bool' w_address = space.call_method(w_leaf, "GetValuePointer") from pypy.module._cffi_backend import cdataobj, newtype cdata = cdataobj.W_CData(space, address, newtype.new_primitive_type(space, typename)) # cache result space.setattr(w_self, space.wrap('_'+attr), space.wrap(cdata)) return space.getattr(w_self, args_w[0])