示例#1
0
 def _build_cpython_func(self, g, fnname):
     # Build a function: in the PyPy version, these are all equivalent
     # and 'g->address' is a pointer to a function of exactly the
     # C type specified --- almost: arguments that are structs or
     # unions are replaced with pointers, and a return value that
     # would be struct or union is instead handled by passing
     # inside the function a hidden first pointer argument.
     rawfunctype = realize_c_type.realize_c_type_or_func(
         self.ffi, self.ctx.c_types, getarg(g.c_type_op))
     assert isinstance(rawfunctype, realize_c_type.W_RawFuncType)
     #
     w_ct, locs = rawfunctype.unwrap_as_nostruct_fnptr(self.ffi)
     #
     ptr = rffi.cast(rffi.CCHARP, g.c_address)
     assert ptr
     return W_FunctionWrapper(self.space, ptr, g.c_size_or_direct_fn, w_ct,
                              locs, rawfunctype, fnname)
示例#2
0
 def _build_cpython_func(self, g, fnname):
     # Build a function: in the PyPy version, these are all equivalent
     # and 'g->address' is a pointer to a function of exactly the
     # C type specified --- almost: arguments that are structs or
     # unions are replaced with pointers, and a return value that
     # would be struct or union is instead handled by passing
     # inside the function a hidden first pointer argument.
     rawfunctype = realize_c_type.realize_c_type_or_func(
         self.ffi, self.ctx.c_types, getarg(g.c_type_op))
     assert isinstance(rawfunctype, realize_c_type.W_RawFuncType)
     #
     rawfunctype.prepare_nostruct_fnptr(self.ffi)
     #
     ptr = rffi.cast(rffi.CCHARP, g.c_address)
     assert ptr
     return W_FunctionWrapper(self.space, ptr, g.c_size_or_direct_fn,
                              rawfunctype, fnname, self.libname)
示例#3
0
def externpy_deco(space, w_ffi, w_python_callable, w_name, w_error, w_onerror):
    from pypy.module._cffi_backend.ffi_obj import W_FFIObject
    from pypy.module._cffi_backend.ccallback import W_ExternPython

    ffi = space.interp_w(W_FFIObject, w_ffi)

    if space.is_w(w_name, space.w_None):
        w_name = space.getattr(w_python_callable, space.wrap('__name__'))
    name = space.str_w(w_name)

    ctx = ffi.ctxobj.ctx
    index = parse_c_type.search_in_globals(ctx, name)
    if index < 0:
        raise externpy_not_found(ffi, name)

    g = ctx.c_globals[index]
    if getop(g.c_type_op) != cffi_opcode.OP_EXTERN_PYTHON:
        raise externpy_not_found(ffi, name)

    w_ct = realize_c_type.realize_c_type(ffi, ctx.c_types, getarg(g.c_type_op))

    # make a W_ExternPython instance, which is nonmovable; then cast it
    # to a raw pointer and assign it to the field 'reserved1' of the
    # externpy object from C.  We must make sure to keep it alive forever,
    # or at least until ffi.def_extern() is used again to change the
    # binding.  Note that the W_ExternPython is never exposed to the user.
    externpy = rffi.cast(parse_c_type.PEXTERNPY, g.c_address)
    externpython = instantiate(W_ExternPython, nonmovable=True)
    cdata = rffi.cast(rffi.CCHARP, externpy)
    W_ExternPython.__init__(externpython, space, cdata,
                          w_ct, w_python_callable, w_error, w_onerror)

    key = rffi.cast(lltype.Signed, externpy)
    space.fromcache(KeepaliveCache).cache_dict[key] = externpython
    externpy.c_reserved1 = externpython.hide_object()

    # return the function object unmodified
    return w_python_callable
示例#4
0
def externpy_deco(space, w_ffi, w_python_callable, w_name, w_error, w_onerror):
    from pypy.module._cffi_backend.ffi_obj import W_FFIObject
    from pypy.module._cffi_backend.ccallback import W_ExternPython

    ffi = space.interp_w(W_FFIObject, w_ffi)

    if space.is_w(w_name, space.w_None):
        w_name = space.getattr(w_python_callable, space.wrap("__name__"))
    name = space.str_w(w_name)

    ctx = ffi.ctxobj.ctx
    index = parse_c_type.search_in_globals(ctx, name)
    if index < 0:
        raise externpy_not_found(ffi, name)

    g = ctx.c_globals[index]
    if getop(g.c_type_op) != cffi_opcode.OP_EXTERN_PYTHON:
        raise externpy_not_found(ffi, name)

    w_ct = realize_c_type.realize_c_type(ffi, ctx.c_types, getarg(g.c_type_op))

    # make a W_ExternPython instance, which is nonmovable; then cast it
    # to a raw pointer and assign it to the field 'reserved1' of the
    # externpy object from C.  We must make sure to keep it alive forever,
    # or at least until ffi.def_extern() is used again to change the
    # binding.  Note that the W_ExternPython is never exposed to the user.
    externpy = rffi.cast(parse_c_type.PEXTERNPY, g.c_address)
    externpython = instantiate(W_ExternPython, nonmovable=True)
    cdata = rffi.cast(rffi.CCHARP, externpy)
    W_ExternPython.__init__(externpython, space, cdata, w_ct, w_python_callable, w_error, w_onerror)

    key = rffi.cast(lltype.Signed, externpy)
    space.fromcache(KeepaliveCache).cache_dict[key] = externpython
    externpy.c_reserved1 = externpython.hide_object()

    # return the function object unmodified
    return w_python_callable
示例#5
0
    def _build_attr(self, attr):
        index = parse_c_type.search_in_globals(self.ctx, attr)
        if index < 0:
            for ffi1, lib1 in self.ffi.included_ffis_libs:
                if lib1 is not None:
                    try:
                        w_result = lib1._get_attr_elidable(attr)
                        break  # found, break out of this loop
                    except KeyError:
                        w_result = lib1._build_attr(attr)
                        if w_result is not None:
                            break  # found, break out of this loop
                else:
                    w_result = ffi1.fetch_int_constant(attr)
                    if w_result is not None:
                        break  # found, break out of this loop
            else:
                return None  # not found at all
        else:
            space = self.space
            g = self.ctx.c_globals[index]
            op = getop(g.c_type_op)
            if (op == cffi_opcode.OP_CPYTHON_BLTN_V
                    or op == cffi_opcode.OP_CPYTHON_BLTN_N
                    or op == cffi_opcode.OP_CPYTHON_BLTN_O):
                # A function
                w_result = self._build_cpython_func(g, attr)
                #
            elif op == cffi_opcode.OP_GLOBAL_VAR:
                # A global variable of the exact type specified here
                w_ct = realize_c_type.realize_c_type(self.ffi,
                                                     self.ctx.c_types,
                                                     getarg(g.c_type_op))
                g_size = rffi.cast(lltype.Signed, g.c_size_or_direct_fn)
                if g_size != w_ct.size and g_size != 0 and w_ct.size > 0:
                    raise oefmt(
                        self.ffi.w_FFIError,
                        "global variable '%s' should be %d bytes "
                        "according to the cdef, but is actually %d", attr,
                        w_ct.size, g_size)
                ptr = rffi.cast(rffi.CCHARP, g.c_address)
                if not ptr:  # for dlopen() style
                    ptr = self.cdlopen_fetch(attr)
                w_result = cglob.W_GlobSupport(space, w_ct, ptr)
                #
            elif (op == cffi_opcode.OP_CONSTANT_INT
                  or op == cffi_opcode.OP_ENUM):
                # A constant integer whose value, in an "unsigned long long",
                # is obtained by calling the function at g->address
                w_result = realize_c_type.realize_global_int(
                    self.ffi, g, index)
                #
            elif (op == cffi_opcode.OP_CONSTANT
                  or op == cffi_opcode.OP_DLOPEN_CONST):
                # A constant which is not of integer type
                w_ct = realize_c_type.realize_c_type(self.ffi,
                                                     self.ctx.c_types,
                                                     getarg(g.c_type_op))
                fetch_funcptr = rffi.cast(realize_c_type.FUNCPTR_FETCH_CHARP,
                                          g.c_address)
                if w_ct.size <= 0:
                    raise oefmt(space.w_SystemError,
                                "constant has no known size")
                if not fetch_funcptr:  # for dlopen() style
                    assert op == cffi_opcode.OP_DLOPEN_CONST
                    ptr = self.cdlopen_fetch(attr)
                else:
                    assert op == cffi_opcode.OP_CONSTANT
                    ptr = lltype.malloc(rffi.CCHARP.TO,
                                        w_ct.size,
                                        flavor='raw')
                    self.ffi._finalizer.free_mems.append(ptr)
                    fetch_funcptr(ptr)
                w_result = w_ct.convert_to_object(ptr)
                #
            elif op == cffi_opcode.OP_DLOPEN_FUNC:
                # For dlopen(): the function of the given 'name'.  We use
                # dlsym() to get the address of something in the dynamic
                # library, which we interpret as being exactly a function of
                # the specified type.
                ptr = self.cdlopen_fetch(attr)
                w_ct = realize_c_type.realize_c_type_or_func(
                    self.ffi, self.ctx.c_types, getarg(g.c_type_op))
                # must have returned a function type:
                assert isinstance(w_ct, realize_c_type.W_RawFuncType)
                w_ctfnptr = w_ct.unwrap_as_fnptr(self.ffi)
                w_result = W_CData(self.space, ptr, w_ctfnptr)
                #
            else:
                raise oefmt(space.w_NotImplementedError,
                            "in lib_build_attr: op=%d", op)

        assert w_result is not None
        self.dict_w[attr] = w_result
        return w_result
示例#6
0
文件: lib_obj.py 项目: mozillazg/pypy
    def _build_attr(self, attr):
        index = parse_c_type.search_in_globals(self.ctx, attr)
        if index < 0:
            for ffi1, lib1 in self.ffi.included_ffis_libs:
                if lib1 is not None:
                    try:
                        w_result = lib1._get_attr_elidable(attr)
                        break           # found, break out of this loop
                    except KeyError:
                        w_result = lib1._build_attr(attr)
                        if w_result is not None:
                            break       # found, break out of this loop
                else:
                    w_result = ffi1.fetch_int_constant(attr)
                    if w_result is not None:
                        break           # found, break out of this loop
            else:
                return None     # not found at all
        else:
            space = self.space
            g = self.ctx.c_globals[index]
            op = getop(g.c_type_op)
            if (op == cffi_opcode.OP_CPYTHON_BLTN_V or
                op == cffi_opcode.OP_CPYTHON_BLTN_N or
                op == cffi_opcode.OP_CPYTHON_BLTN_O):
                # A function
                w_result = self._build_cpython_func(g, attr)
                #
            elif op == cffi_opcode.OP_GLOBAL_VAR:
                # A global variable of the exact type specified here
                # (nowadays, only used by the ABI mode or backend
                # compatibility; see OP_GLOBAL_F for the API mode
                w_ct = realize_c_type.realize_c_type(
                    self.ffi, self.ctx.c_types, getarg(g.c_type_op))
                g_size = rffi.cast(lltype.Signed, g.c_size_or_direct_fn)
                if g_size != w_ct.size and g_size != 0 and w_ct.size > 0:
                    raise oefmt(self.ffi.w_FFIError,
                            "global variable '%s' should be %d bytes "
                            "according to the cdef, but is actually %d",
                            attr, w_ct.size, g_size)
                ptr = rffi.cast(rffi.CCHARP, g.c_address)
                if not ptr:   # for dlopen() style
                    ptr = self.cdlopen_fetch(attr)
                w_result = cglob.W_GlobSupport(space, attr, w_ct, ptr=ptr)
                #
            elif op == cffi_opcode.OP_GLOBAL_VAR_F:
                w_ct = realize_c_type.realize_c_type(
                    self.ffi, self.ctx.c_types, getarg(g.c_type_op))
                w_result = cglob.W_GlobSupport(space, attr, w_ct,
                                               fetch_addr=g.c_address)
                #
            elif (op == cffi_opcode.OP_CONSTANT_INT or
                  op == cffi_opcode.OP_ENUM):
                # A constant integer whose value, in an "unsigned long long",
                # is obtained by calling the function at g->address
                w_result = realize_c_type.realize_global_int(self.ffi, g,
                                                             index)
                #
            elif (op == cffi_opcode.OP_CONSTANT or
                  op == cffi_opcode.OP_DLOPEN_CONST):
                # A constant which is not of integer type
                w_ct = realize_c_type.realize_c_type(
                    self.ffi, self.ctx.c_types, getarg(g.c_type_op))
                fetch_funcptr = rffi.cast(
                    realize_c_type.FUNCPTR_FETCH_CHARP,
                    g.c_address)
                if w_ct.size <= 0:
                    raise oefmt(self.ffi.w_FFIError,
                                "constant '%s' is of type '%s', "
                                "whose size is not known", attr, w_ct.name)
                    raise oefmt(space.w_SystemError,
                                "constant has no known size")
                if not fetch_funcptr:   # for dlopen() style
                    assert op == cffi_opcode.OP_DLOPEN_CONST
                    ptr = self.cdlopen_fetch(attr)
                else:
                    assert op == cffi_opcode.OP_CONSTANT
                    ptr = lltype.malloc(rffi.CCHARP.TO, w_ct.size, flavor='raw')
                    self.ffi._finalizer.free_mems.append(ptr)
                    fetch_funcptr(ptr)
                w_result = w_ct.convert_to_object(ptr)
                #
            elif op == cffi_opcode.OP_DLOPEN_FUNC:
                # For dlopen(): the function of the given 'name'.  We use
                # dlsym() to get the address of something in the dynamic
                # library, which we interpret as being exactly a function of
                # the specified type.
                ptr = self.cdlopen_fetch(attr)
                w_ct = realize_c_type.realize_c_type_or_func(
                    self.ffi, self.ctx.c_types, getarg(g.c_type_op))
                # must have returned a function type:
                assert isinstance(w_ct, realize_c_type.W_RawFuncType)
                w_ctfnptr = w_ct.unwrap_as_fnptr(self.ffi)
                w_result = W_CData(self.space, ptr, w_ctfnptr)
                #
                #
            elif op == cffi_opcode.OP_EXTERN_PYTHON:
                # for reading 'lib.bar' where bar is declared
                # as an extern "Python"
                w_ct = realize_c_type.realize_c_type(
                    self.ffi, self.ctx.c_types, getarg(g.c_type_op))
                ptr = lltype.direct_fieldptr(g, 'c_size_or_direct_fn')
                w_result = w_ct.convert_to_object(rffi.cast(rffi.CCHARP, ptr))
            else:
                raise oefmt(space.w_NotImplementedError,
                            "in lib_build_attr: op=%d", op)

        assert w_result is not None
        self.dict_w[attr] = w_result
        return w_result