pypy / pypy / module / _cffi_backend /

from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.gateway import interp2app
from pypy.interpreter.typedef import TypeDef
from pypy.interpreter.typedef import make_weakref_descr
from pypy.rpython.lltypesystem import lltype, llmemory, rffi
from pypy.rlib.objectmodel import we_are_translated

from pypy.module._cffi_backend import cdataobj

class W_CType(Wrappable):
    _attrs_   = ['space', 'size',  'name', 'name_position', '_lifeline_']
    _immutable_fields_ = ['size?', 'name', 'name_position']
    # note that 'size' is not strictly immutable, because it can change
    # from -1 to the real value in the W_CTypeStruct subclass.

    cast_anything = False
    is_primitive_integer = False

    def __init__(self, space, size, name, name_position): = space
        self.size = size     # size of instances, or -1 if unknown = name     # the name of the C type as a string
        self.name_position = name_position
        # 'name_position' is the index in 'name' where it must be extended,
        # e.g. with a '*' or a variable name.

    def repr(self):
        space =
        return space.wrap("<ctype '%s'>" % (,))

    def extra_repr(self, cdata):
        if cdata:
            return '0x%x' % rffi.cast(lltype.Unsigned, cdata)
            return 'NULL'

    def is_char_ptr_or_array(self):
        return False

    def is_unichar_ptr_or_array(self):
        return False

    def newp(self, w_init):
        space =
        raise operationerrfmt(space.w_TypeError,
                              "expected a pointer or array ctype, got '%s'",

    def cast(self, w_ob):
        space =
        raise operationerrfmt(space.w_TypeError,
                              "cannot cast to '%s'",

    def int(self, cdata):
        space =
        raise operationerrfmt(space.w_TypeError,
                              "int() not supported on cdata '%s'",

    def float(self, cdata):
        space =
        raise operationerrfmt(space.w_TypeError,
                              "float() not supported on cdata '%s'",

    def convert_to_object(self, cdata):
        space =
        raise operationerrfmt(space.w_TypeError,
                              "cannot return a cdata '%s'",

    def convert_from_object(self, cdata, w_ob):
        space =
        raise operationerrfmt(space.w_TypeError,
                              "cannot initialize cdata '%s'",

    def convert_argument_from_object(self, cdata, w_ob):
        self.convert_from_object(cdata, w_ob)
        return False

    def _convert_error(self, expected, w_got):
        space =
        ob = space.interpclass_w(w_got)
        if isinstance(ob, cdataobj.W_CData):
            return operationerrfmt(space.w_TypeError,
                                   "initializer for ctype '%s' must be a %s, "
                                   "not cdata '%s'",, expected,
            return operationerrfmt(space.w_TypeError,
                                   "initializer for ctype '%s' must be a %s, "
                                   "not %s",, expected,

    def _check_subscript_index(self, w_cdata, i):
        space =
        raise operationerrfmt(space.w_TypeError,
                              "cdata of type '%s' cannot be indexed",

    def string(self, cdataobj, maxlen):
        space =
        raise operationerrfmt(space.w_TypeError,
                              "string(): unexpected cdata '%s' argument",

    def add(self, cdata, i):
        space =
        raise operationerrfmt(space.w_TypeError,
                              "cannot add a cdata '%s' and a number",

    def insert_name(self, extra, extra_position):
        name = '%s%s%s' % ([:self.name_position],
        name_position = self.name_position + extra_position
        return name, name_position

    def alignof(self):
        align = self._alignof()
        if not we_are_translated():
            # obscure hack when untranslated, maybe, approximate, don't use
            if isinstance(align, llmemory.FieldOffset):
                align = rffi.sizeof(align.TYPE.y)
            # a different hack when translated, to avoid seeing constants
            # of a symbolic integer type
            align = llmemory.raw_malloc_usage(align)
        return align

    def _alignof(self):
        space =
        raise operationerrfmt(space.w_TypeError,
                              "ctype '%s' is of unknown alignment",

    def offsetof(self, fieldname):
        space =
        raise OperationError(space.w_TypeError,
                             space.wrap("not a struct or union ctype"))

    def _getfields(self):
        return None

    def call(self, funcaddr, args_w):
        space =
        raise operationerrfmt(space.w_TypeError,
                              "cdata '%s' is not callable",

    def iter(self, cdata):
        space =
        raise operationerrfmt(space.w_TypeError,
                              "cdata '%s' does not support iteration",

    def get_vararg_type(self):
        return self

    def getcfield(self, attr):
        space =
        raise operationerrfmt(space.w_AttributeError,
                              "cdata '%s' has no attribute '%s'",
                    , attr)

    def copy_and_convert_to_object(self, cdata):
        return self.convert_to_object(cdata)

W_CType.typedef = TypeDef(
    __module__ = '_cffi_backend',
    __repr__ = interp2app(W_CType.repr),
    __weakref__ = make_weakref_descr(W_CType),
W_CType.typedef.acceptable_as_base_class = False