예제 #1
0
파일: cint_capi.py 프로젝트: Darriall/pypy
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
예제 #2
0
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
예제 #3
0
 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)
예제 #4
0
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
예제 #5
0
    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
예제 #6
0
파일: ctypeprim.py 프로젝트: zielmicha/pypy
 def get_vararg_type(self):
     from pypy.module._cffi_backend import newtype
     return newtype.new_primitive_type(self.space, "int")
예제 #7
0
파일: ctypeprim.py 프로젝트: zielmicha/pypy
 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
예제 #8
0
    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
예제 #9
0
파일: cint_capi.py 프로젝트: sota/pypy-old
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])
예제 #10
0
파일: cint_capi.py 프로젝트: sota/pypy-old
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
예제 #11
0
파일: cint_capi.py 프로젝트: charred/pypy
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])