Example #1
0
 def __init__(self, space, cdata, ctype, w_callable, w_error, w_onerror):
     W_CData.__init__(self, space, cdata, ctype)
     #
     if not space.is_true(space.callable(w_callable)):
         raise oefmt(space.w_TypeError,
                     "expected a callable object, not %T", w_callable)
     self.w_callable = w_callable
     if not space.is_none(w_onerror):
         if not space.is_true(space.callable(w_onerror)):
             raise oefmt(space.w_TypeError,
                         "expected a callable object for 'onerror', not %T",
                         w_onerror)
         self.w_onerror = w_onerror
     #
     fresult = self.getfunctype().ctitem
     size = fresult.size
     if size < 0:
         size = 0
     elif fresult.is_primitive_integer and size < SIZE_OF_FFI_ARG:
         size = SIZE_OF_FFI_ARG
     with lltype.scoped_alloc(rffi.CCHARP.TO, size, zero=True) as ll_error:
         if not space.is_none(w_error):
             convert_from_object_fficallback(fresult, ll_error, w_error,
                                          self.decode_args_from_libffi)
         self.error_string = rffi.charpsize2str(ll_error, size)
     #
     # We must setup the GIL here, in case the callback is invoked in
     # some other non-Pythonic thread.  This is the same as cffi on
     # CPython, or ctypes.
     if space.config.translation.thread:
         from pypy.module.thread.os_thread import setup_threads
         setup_threads(space)
Example #2
0
 def __init__(self, space, ctype, w_callable, w_error):
     raw_closure = rffi.cast(rffi.CCHARP, clibffi.closureHeap.alloc())
     W_CData.__init__(self, space, raw_closure, ctype)
     #
     if not space.is_true(space.callable(w_callable)):
         raise operationerrfmt(space.w_TypeError,
                               "expected a callable object, not %T",
                               w_callable)
     self.w_callable = w_callable
     #
     fresult = self.getfunctype().ctitem
     size = fresult.size
     if size > 0:
         if fresult.is_primitive_integer and size < SIZE_OF_FFI_ARG:
             size = SIZE_OF_FFI_ARG
         self.ll_error = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw',
                                       zero=True)
     if not space.is_none(w_error):
         convert_from_object_fficallback(fresult, self.ll_error, w_error)
     #
     self.unique_id = compute_unique_id(self)
     global_callback_mapping.set(self.unique_id, self)
     #
     cif_descr = self.getfunctype().cif_descr
     if not cif_descr:
         raise OperationError(space.w_NotImplementedError,
                              space.wrap("callbacks with '...'"))
     res = clibffi.c_ffi_prep_closure(self.get_closure(), cif_descr.cif,
                                      invoke_callback,
                                      rffi.cast(rffi.VOIDP, self.unique_id))
     if rffi.cast(lltype.Signed, res) != clibffi.FFI_OK:
         raise OperationError(space.w_SystemError,
             space.wrap("libffi failed to build this callback"))
Example #3
0
 def __init__(self, space, cdata, ctype, w_callable, w_error, w_onerror):
     W_CData.__init__(self, space, cdata, ctype)
     #
     if not space.is_true(space.callable(w_callable)):
         raise oefmt(space.w_TypeError,
                     "expected a callable object, not %T", w_callable)
     self.w_callable = w_callable
     if not space.is_none(w_onerror):
         if not space.is_true(space.callable(w_onerror)):
             raise oefmt(space.w_TypeError,
                         "expected a callable object for 'onerror', not %T",
                         w_onerror)
         self.w_onerror = w_onerror
     #
     fresult = self.getfunctype().ctitem
     size = fresult.size
     if size < 0:
         size = 0
     elif fresult.is_primitive_integer and size < SIZE_OF_FFI_ARG:
         size = SIZE_OF_FFI_ARG
     with lltype.scoped_alloc(rffi.CCHARP.TO, size, zero=True) as ll_error:
         if not space.is_none(w_error):
             convert_from_object_fficallback(fresult, ll_error, w_error,
                                          self.decode_args_from_libffi)
         self.error_string = rffi.charpsize2str(ll_error, size)
     #
     # We must setup the GIL here, in case the callback is invoked in
     # some other non-Pythonic thread.  This is the same as cffi on
     # CPython, or ctypes.
     if space.config.translation.thread:
         from pypy.module.thread.os_thread import setup_threads
         setup_threads(space)
Example #4
0
 def __init__(self, space, ctype, w_callable, w_error, w_onerror):
     raw_closure = rffi.cast(rffi.CCHARP, clibffi.closureHeap.alloc())
     W_CData.__init__(self, space, raw_closure, ctype)
     #
     if not space.is_true(space.callable(w_callable)):
         raise oefmt(space.w_TypeError,
                     "expected a callable object, not %T", w_callable)
     self.w_callable = w_callable
     if not space.is_none(w_onerror):
         if not space.is_true(space.callable(w_onerror)):
             raise oefmt(
                 space.w_TypeError,
                 "expected a callable object for 'onerror', not %T",
                 w_onerror)
         self.w_onerror = w_onerror
     #
     fresult = self.getfunctype().ctitem
     size = fresult.size
     if size > 0:
         if fresult.is_primitive_integer and size < SIZE_OF_FFI_ARG:
             size = SIZE_OF_FFI_ARG
         self.ll_error = lltype.malloc(rffi.CCHARP.TO,
                                       size,
                                       flavor='raw',
                                       zero=True)
     if not space.is_none(w_error):
         convert_from_object_fficallback(fresult, self.ll_error, w_error)
     #
     self.unique_id = compute_unique_id(self)
     global_callback_mapping.set(self.unique_id, self)
     #
     cif_descr = self.getfunctype().cif_descr
     if not cif_descr:
         raise oefmt(
             space.w_NotImplementedError,
             "%s: callback with unsupported argument or "
             "return type or with '...'",
             self.getfunctype().name)
     with self as ptr:
         closure_ptr = rffi.cast(clibffi.FFI_CLOSUREP, ptr)
         unique_id = rffi.cast(rffi.VOIDP, self.unique_id)
         res = clibffi.c_ffi_prep_closure(closure_ptr, cif_descr.cif,
                                          invoke_callback, unique_id)
     if rffi.cast(lltype.Signed, res) != clibffi.FFI_OK:
         raise OperationError(
             space.w_SystemError,
             space.wrap("libffi failed to build this callback"))
     #
     # We must setup the GIL here, in case the callback is invoked in
     # some other non-Pythonic thread.  This is the same as cffi on
     # CPython.
     if space.config.translation.thread:
         from pypy.module.thread.os_thread import setup_threads
         setup_threads(space)
Example #5
0
 def __init__(self, space, ctype, w_callable, w_error, w_onerror):
     raw_closure = rffi.cast(rffi.CCHARP, clibffi.closureHeap.alloc())
     W_CData.__init__(self, space, raw_closure, ctype)
     #
     if not space.is_true(space.callable(w_callable)):
         raise oefmt(space.w_TypeError,
                     "expected a callable object, not %T", w_callable)
     self.w_callable = w_callable
     if not space.is_none(w_onerror):
         if not space.is_true(space.callable(w_onerror)):
             raise oefmt(space.w_TypeError,
                         "expected a callable object for 'onerror', not %T",
                         w_onerror)
         self.w_onerror = w_onerror
     #
     fresult = self.getfunctype().ctitem
     size = fresult.size
     if size > 0:
         if fresult.is_primitive_integer and size < SIZE_OF_FFI_ARG:
             size = SIZE_OF_FFI_ARG
         self.ll_error = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw',
                                       zero=True)
     if not space.is_none(w_error):
         convert_from_object_fficallback(fresult, self.ll_error, w_error)
     #
     self.unique_id = compute_unique_id(self)
     global_callback_mapping.set(self.unique_id, self)
     #
     cif_descr = self.getfunctype().cif_descr
     if not cif_descr:
         raise oefmt(space.w_NotImplementedError,
                     "%s: callback with unsupported argument or "
                     "return type or with '...'", self.getfunctype().name)
     with self as ptr:
         closure_ptr = rffi.cast(clibffi.FFI_CLOSUREP, ptr)
         unique_id = rffi.cast(rffi.VOIDP, self.unique_id)
         res = clibffi.c_ffi_prep_closure(closure_ptr, cif_descr.cif,
                                          invoke_callback,
                                          unique_id)
     if rffi.cast(lltype.Signed, res) != clibffi.FFI_OK:
         raise OperationError(space.w_SystemError,
             space.wrap("libffi failed to build this callback"))
     #
     # We must setup the GIL here, in case the callback is invoked in
     # some other non-Pythonic thread.  This is the same as cffi on
     # CPython.
     if space.config.translation.thread:
         from pypy.module.thread.os_thread import setup_threads
         setup_threads(space)
Example #6
0
    def descr_addressof(self, w_arg, args_w):
        """\
Limited equivalent to the '&' operator in C:

1. ffi.addressof(<cdata 'struct-or-union'>) returns a cdata that is a
pointer to this struct or union.

2. ffi.addressof(<cdata>, field-or-index...) returns the address of a
field or array item inside the given structure or array, recursively
in case of nested structures or arrays.

3. ffi.addressof(<library>, "name") returns the address of the named
function or global variable."""
        #
        from pypy.module._cffi_backend.lib_obj import W_LibObject
        space = self.space
        if isinstance(w_arg, W_LibObject) and len(args_w) == 1:
            # case 3 in the docstring
            return w_arg.address_of_func_or_global_var(space.text_w(args_w[0]))
        #
        w_ctype = self.ffi_type(w_arg, ACCEPT_CDATA)
        if len(args_w) == 0:
            # case 1 in the docstring
            if (not isinstance(w_ctype, ctypestruct.W_CTypeStructOrUnion)
                    and not isinstance(w_ctype, ctypearray.W_CTypeArray)):
                raise oefmt(space.w_TypeError,
                            "expected a cdata struct/union/array object")
            offset = 0
        else:
            # case 2 in the docstring
            if (not isinstance(w_ctype, ctypestruct.W_CTypeStructOrUnion)
                    and not isinstance(w_ctype, ctypearray.W_CTypeArray)
                    and not isinstance(w_ctype, ctypeptr.W_CTypePointer)):
                raise oefmt(
                    space.w_TypeError,
                    "expected a cdata struct/union/array/pointer object")
            if len(args_w) == 1:
                w_ctype, offset = w_ctype.direct_typeoffsetof(args_w[0], False)
            else:
                w_ctype, offset = self._more_addressof(args_w, w_ctype)
        #
        assert isinstance(w_arg, W_CData)
        cdata = w_arg.unsafe_escaping_ptr()
        cdata = rffi.ptradd(cdata, offset)
        w_ctypeptr = newtype.new_pointer_type(space, w_ctype)
        return W_CData(space, cdata, w_ctypeptr)
Example #7
0
 def load_function(self, w_ctype, name):
     from pypy.module._cffi_backend import ctypeptr, ctypearray
     self.check_closed()
     space = self.space
     #
     if not isinstance(w_ctype, ctypeptr.W_CTypePtrOrArray):
         raise oefmt(space.w_TypeError,
                     "function or pointer or array cdata expected, got '%s'",
                     w_ctype.name)
     #
     try:
         cdata = dlsym(self.handle, name)
     except KeyError:
         raise oefmt(space.w_AttributeError,
                     "function/symbol '%s' not found in library '%s'",
                     name, self.name)
     if isinstance(w_ctype, ctypearray.W_CTypeArray) and w_ctype.length < 0:
         w_ctype = w_ctype.ctptr
     return W_CData(space, rffi.cast(rffi.CCHARP, cdata), w_ctype)
Example #8
0
 def load_function(self, w_ctype, name):
     from pypy.module._cffi_backend import ctypefunc, ctypeptr, ctypevoid
     space = self.space
     #
     ok = False
     if isinstance(w_ctype, ctypefunc.W_CTypeFunc):
         ok = True
     if (isinstance(w_ctype, ctypeptr.W_CTypePointer)
             and isinstance(w_ctype.ctitem, ctypevoid.W_CTypeVoid)):
         ok = True
     if not ok:
         raise oefmt(space.w_TypeError, "function cdata expected, got '%s'",
                     w_ctype.name)
     #
     try:
         cdata = dlsym(self.handle, name)
     except KeyError:
         raise oefmt(space.w_KeyError,
                     "function '%s' not found in library '%s'", name,
                     self.name)
     return W_CData(space, rffi.cast(rffi.CCHARP, cdata), w_ctype)
Example #9
0
 def address_of_func_or_global_var(self, varname):
     # rebuild a string object from 'varname', to do typechecks and
     # to force a unicode back to a plain string
     space = self.space
     w_value = self._get_attr(space.wrap(varname))
     if isinstance(w_value, cglob.W_GlobSupport):
         # regular case: a global variable
         return w_value.address()
     #
     if isinstance(w_value, W_FunctionWrapper):
         # '&func' returns a regular cdata pointer-to-function
         if w_value.directfnptr:
             return W_CData(space, w_value.directfnptr, w_value.ctype)
         else:
             return w_value  # backward compatibility
     #
     if (isinstance(w_value, W_CData)
             and isinstance(w_value.ctype, W_CTypeFunc)):
         # '&func' is 'func' in C, for a constant function 'func'
         return w_value
     #
     raise oefmt(space.w_AttributeError,
                 "cannot take the address of the constant '%s'", varname)
Example #10
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
Example #11
0
 def address(self):
     w_ctypeptr = newtype.new_pointer_type(self.space, self.w_ctype)
     return W_CData(self.space, self.fetch_global_var_addr(), w_ctypeptr)