Пример #1
0
def get_converter(space, name, default):
    # The matching of the name to a converter should follow:
    #   1) full, exact match
    #       1a) const-removed match
    #   2) match of decorated, unqualified type
    #   3) accept ref as pointer (for the stubs, const& can be
    #       by value, but that does not work for the ffi path)
    #   4) generalized cases (covers basically all user classes)
    #   5) void converter, which fails on use

    name = capi.c_resolve_name(space, name)

    #   1) full, exact match
    try:
        return _converters[name](space, default)
    except KeyError:
        pass

    #   1a) const-removed match
    try:
        return _converters[helper.remove_const(name)](space, default)
    except KeyError:
        pass

    #   2) match of decorated, unqualified type
    compound = helper.compound(name)
    clean_name = capi.c_resolve_name(space, helper.clean_type(name))
    try:
        # array_index may be negative to indicate no size or no size found
        array_size = helper.array_size(name)
        return _a_converters[clean_name + compound](space, array_size)
    except KeyError:
        pass

    #   3) TODO: accept ref as pointer

    #   4) generalized cases (covers basically all user classes)
    from pypy.module.cppyy import interp_cppyy
    cppclass = interp_cppyy.scope_byname(space, clean_name)
    if cppclass:
        # type check for the benefit of the annotator
        from pypy.module.cppyy.interp_cppyy import W_CPPClass
        cppclass = space.interp_w(W_CPPClass, cppclass, can_be_None=False)
        if compound == "*":
            return InstancePtrConverter(space, cppclass)
        elif compound == "&":
            return InstanceRefConverter(space, cppclass)
        elif compound == "**":
            return InstancePtrPtrConverter(space, cppclass)
        elif compound == "":
            return InstanceConverter(space, cppclass)
    elif capi.c_is_enum(space, clean_name):
        return _converters['unsigned'](space, default)

    #   5) void converter, which fails on use
    #
    # return a void converter here, so that the class can be build even
    # when some types are unknown; this overload will simply fail on use
    return VoidConverter(space, name)
Пример #2
0
def get_converter(space, name, default):
    # The matching of the name to a converter should follow:
    #   1) full, exact match
    #       1a) const-removed match
    #   2) match of decorated, unqualified type
    #   3) accept ref as pointer (for the stubs, const& can be
    #       by value, but that does not work for the ffi path)
    #   4) generalized cases (covers basically all user classes)
    #   5) void converter, which fails on use

    name = capi.c_resolve_name(space, name)

    #   1) full, exact match
    try:
        return _converters[name](space, default)
    except KeyError:
        pass

    #   1a) const-removed match
    try:
        return _converters[helper.remove_const(name)](space, default)
    except KeyError:
        pass

    #   2) match of decorated, unqualified type
    compound = helper.compound(name)
    clean_name = capi.c_resolve_name(space, helper.clean_type(name))
    try:
        # array_index may be negative to indicate no size or no size found
        array_size = helper.array_size(name)
        return _a_converters[clean_name+compound](space, array_size)
    except KeyError:
        pass

    #   3) TODO: accept ref as pointer

    #   4) generalized cases (covers basically all user classes)
    from pypy.module.cppyy import interp_cppyy
    cppclass = interp_cppyy.scope_byname(space, clean_name)
    if cppclass:
        # type check for the benefit of the annotator
        from pypy.module.cppyy.interp_cppyy import W_CPPClass
        cppclass = space.interp_w(W_CPPClass, cppclass, can_be_None=False)
        if compound == "*":
            return InstancePtrConverter(space, cppclass)
        elif compound == "&":
            return InstanceRefConverter(space, cppclass)
        elif compound == "**":
            return InstancePtrPtrConverter(space, cppclass)
        elif compound == "":
            return InstanceConverter(space, cppclass)
    elif capi.c_is_enum(space, clean_name):
        return _converters['unsigned'](space, default)

    #   5) void converter, which fails on use
    #
    # return a void converter here, so that the class can be build even
    # when some types are unknown; this overload will simply fail on use
    return VoidConverter(space, name)
Пример #3
0
def get_executor(space, name):
    # Matching of 'name' to an executor factory goes through up to four levels:
    #   1) full, qualified match
    #   2) drop '&': by-ref is pretty much the same as by-value, python-wise
    #   3) types/classes, either by ref/ptr or by value
    #   4) additional special cases
    #
    # If all fails, a default is used, which can be ignored at least until use.

    name = capi.c_resolve_name(space, name)

    #   1) full, qualified match
    try:
        return _executors[name](space, None)
    except KeyError:
        pass

    compound = helper.compound(name)
    clean_name = capi.c_resolve_name(space, helper.clean_type(name))

    #   1a) clean lookup
    try:
        return _executors[clean_name + compound](space, None)
    except KeyError:
        pass

    #   2) drop '&': by-ref is pretty much the same as by-value, python-wise
    if compound and compound[len(compound) - 1] == '&':
        # TODO: this does not actually work with Reflex (?)
        try:
            return _executors[clean_name](space, None)
        except KeyError:
            pass

    #   3) types/classes, either by ref/ptr or by value
    from pypy.module.cppyy import interp_cppyy
    cppclass = interp_cppyy.scope_byname(space, clean_name)
    if cppclass:
        # type check for the benefit of the annotator
        from pypy.module.cppyy.interp_cppyy import W_CPPClass
        cppclass = space.interp_w(W_CPPClass, cppclass, can_be_None=False)
        if compound == '':
            return InstanceExecutor(space, cppclass)
        elif compound == '*' or compound == '&':
            return InstancePtrExecutor(space, cppclass)
        elif compound == '**' or compound == '*&':
            return InstancePtrPtrExecutor(space, cppclass)
    elif capi.c_is_enum(space, clean_name):
        return _executors['unsigned int'](space, None)

    # 4) additional special cases
    if compound == '*':
        return _executors['void*'](
            space, None)  # allow at least passing of the pointer

    # currently used until proper lazy instantiation available in interp_cppyy
    return FunctionExecutor(space, None)
Пример #4
0
def get_executor(space, name):
    # Matching of 'name' to an executor factory goes through up to four levels:
    #   1) full, qualified match
    #   2) drop '&': by-ref is pretty much the same as by-value, python-wise
    #   3) types/classes, either by ref/ptr or by value
    #   4) additional special cases
    #
    # If all fails, a default is used, which can be ignored at least until use.

    name = capi.c_resolve_name(space, name)

    #   1) full, qualified match
    try:
        return _executors[name](space, None)
    except KeyError:
        pass

    compound = helper.compound(name)
    clean_name = capi.c_resolve_name(space, helper.clean_type(name))

    #   1a) clean lookup
    try:
        return _executors[clean_name+compound](space, None)
    except KeyError:
        pass

    #   2) drop '&': by-ref is pretty much the same as by-value, python-wise
    if compound and compound[len(compound)-1] == '&':
        # TODO: this does not actually work with Reflex (?)
        try:
            return _executors[clean_name](space, None)
        except KeyError:
            pass

    #   3) types/classes, either by ref/ptr or by value
    from pypy.module.cppyy import interp_cppyy
    cppclass = interp_cppyy.scope_byname(space, clean_name)
    if cppclass:
        # type check for the benefit of the annotator
        from pypy.module.cppyy.interp_cppyy import W_CPPClass
        cppclass = space.interp_w(W_CPPClass, cppclass, can_be_None=False)
        if compound == '':
            return InstanceExecutor(space, cppclass)
        elif compound == '*' or compound == '&':
            return InstancePtrExecutor(space, cppclass)
        elif compound == '**' or compound == '*&':
            return InstancePtrPtrExecutor(space, cppclass)
    elif capi.c_is_enum(space, clean_name):
        return _executors['unsigned int'](space, None)

    # 4) additional special cases
    if compound == '*':
        return _executors['void*'](space, None)  # allow at least passing of the pointer

    # currently used until proper lazy instantiation available in interp_cppyy
    return FunctionExecutor(space, None)
Пример #5
0
def scope_byname(space, name):
    true_name = capi.c_resolve_name(name)

    state = space.fromcache(State)
    try:
        return state.cppscope_cache[true_name]
    except KeyError:
        pass

    opaque_handle = capi.c_get_scope_opaque(true_name)
    assert lltype.typeOf(opaque_handle) == capi.C_SCOPE
    if opaque_handle:
        final_name = capi.c_final_name(opaque_handle)
        if capi.c_is_namespace(opaque_handle):
            cppscope = W_CPPNamespace(space, final_name, opaque_handle)
        elif capi.c_has_complex_hierarchy(opaque_handle):
            cppscope = W_ComplexCPPClass(space, final_name, opaque_handle)
        else:
            cppscope = W_CPPClass(space, final_name, opaque_handle)
        state.cppscope_cache[name] = cppscope

        cppscope._find_methods()
        cppscope._find_datamembers()
        return cppscope

    return None
Пример #6
0
 def call(self, cppthis, args_w):
     assert lltype.typeOf(cppthis) == capi.C_OBJECT
     for i in range(len(args_w)):
         try:
             s = self.space.str_w(args_w[i])
         except OperationError:
             s = self.space.str_w(self.space.getattr(args_w[i], self.space.wrap('__name__')))
         s = capi.c_resolve_name(self.space, s)
         if s != self.templ_args[i]:
             raise OperationError(self.space.w_TypeError, self.space.wrap(
                 "non-matching template (got %s where %s expected" % (s, self.templ_args[i])))
     return W_CPPBoundMethod(cppthis, self)
Пример #7
0
def map_operator_name(space, cppname, nargs, result_type):
    from pypy.module.cppyy import capi

    if cppname[0:8] == "operator":
        op = cppname[8:].strip(' ')

        # look for known mapping
        try:
            return _operator_mappings[op]
        except KeyError:
            pass

        # return-type dependent mapping
        if op == "[]":
            if result_type.find("const") != 0:
                cpd = compound(result_type)
                if cpd and cpd[len(cpd)-1] == "&":
                    return "__setitem__"
            return "__getitem__"

        # a couple more cases that depend on whether args were given

        if op == "*":   # dereference (not python) vs. multiplication
            return nargs and "__mul__" or "__deref__"

        if op == "+":   # unary positive vs. binary addition
            return nargs and  "__add__" or "__pos__"

        if op == "-":   # unary negative vs. binary subtraction
            return nargs and "__sub__" or "__neg__"

        if op == "++":  # prefix v.s. postfix increment (not python)
            return nargs and "__postinc__" or "__preinc__"

        if op == "--":  # prefix v.s. postfix decrement (not python)
            return nargs and "__postdec__" or "__predec__"

        # operator could have been a conversion using a typedef (this lookup
        # is put at the end only as it is unlikely and may trigger unwanted
        # errors in class loaders in the backend, because a typical operator
        # name is illegal as a class name)
        true_op = capi.c_resolve_name(space, op)

        try:
            return _operator_mappings[true_op]
        except KeyError:
            pass

    # might get here, as not all operator methods handled (although some with
    # no python equivalent, such as new, delete, etc., are simply retained)
    # TODO: perhaps absorb or "pythonify" these operators?
    return cppname
Пример #8
0
def resolve_name(space, name):
    return space.wrap(capi.c_resolve_name(name))
Пример #9
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])
Пример #10
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])