summaryrefslogtreecommitdiff
path: root/cffi/verifier.py
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2012-07-28 22:38:07 +0200
committerArmin Rigo <arigo@tunes.org>2012-07-28 22:38:07 +0200
commitad729259d4fc96fc68215056c5f5ed9cad44a794 (patch)
tree0957a882902708ce617800d3568b60a81c9e81fb /cffi/verifier.py
parent55c5e2e47f961face24f6e5bb1d1849a9dd1a35c (diff)
parent443dd327d32cf1322889693f84cf43fdc18a7324 (diff)
downloadcffi-ad729259d4fc96fc68215056c5f5ed9cad44a794.tar.gz
hg merge default
Diffstat (limited to 'cffi/verifier.py')
-rw-r--r--cffi/verifier.py582
1 files changed, 143 insertions, 439 deletions
diff --git a/cffi/verifier.py b/cffi/verifier.py
index 0661cd9..2e775ae 100644
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -16,7 +16,7 @@ class Verifier(object):
self.preamble = preamble
self.kwds = kwds
#
- key = '\x00'.join(['1', sys.version[:3], __version__, preamble] +
+ key = '\x00'.join(['2', sys.version[:3], __version__, preamble] +
ffi._cdefsources)
k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff).lstrip('0').rstrip('L')
k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff).lstrip('0').rstrip('L')
@@ -81,26 +81,11 @@ class Verifier(object):
if f is not None:
f.close()
self.modulefilename = filename
- self._collect_types()
self._status = 'module'
def _prnt(self, what=''):
print >> self._f, what
- def _gettypenum(self, type):
- # a KeyError here is a bug. please report it! :-)
- return self._typesdict[type]
-
- def _collect_types(self):
- self._typesdict = {}
- self._generate("collecttype")
-
- def _do_collect_type(self, tp):
- if (not isinstance(tp, model.PrimitiveType) and
- tp not in self._typesdict):
- num = len(self._typesdict)
- self._typesdict[tp] = num
-
def _write_source(self, file=None):
must_close = (file is None)
if must_close:
@@ -116,64 +101,15 @@ class Verifier(object):
self._status = 'source'
def _write_source_to_f(self):
- self._collect_types()
- #
- # The new module will have a _cffi_setup() function that receives
- # objects from the ffi world, and that calls some setup code in
- # the module. This setup code is split in several independent
- # functions, e.g. one per constant. The functions are "chained"
- # by ending in a tail call to each other.
- #
- # This is further split in two chained lists, depending on if we
- # can do it at import-time or if we must wait for _cffi_setup() to
- # provide us with the <ctype> objects. This is needed because we
- # need the values of the enum constants in order to build the
- # <ctype 'enum'> that we may have to pass to _cffi_setup().
- #
- # The following two 'chained_list_constants' items contains
- # the head of these two chained lists, as a string that gives the
- # call to do, if any.
- self._chained_list_constants = ['0', '0']
- #
prnt = self._prnt
- # first paste some standard set of lines that are mostly '#define'
+ # first paste some standard set of lines that are mostly '#include'
prnt(cffimod_header)
- prnt()
# then paste the C source given by the user, verbatim.
prnt(self.preamble)
- prnt()
#
# call generate_cpy_xxx_decl(), for every xxx found from
# ffi._parser._declarations. This generates all the functions.
self._generate("decl")
- #
- # implement the function _cffi_setup_custom() as calling the
- # head of the chained list.
- self._generate_setup_custom()
- prnt()
- #
- # produce the method table, including the entries for the
- # generated Python->C function wrappers, which are done
- # by generate_cpy_function_method().
- prnt('static PyMethodDef _cffi_methods[] = {')
- self._generate("method")
- prnt(' {"_cffi_setup", _cffi_setup, METH_VARARGS},')
- prnt(' {NULL, NULL} /* Sentinel */')
- prnt('};')
- prnt()
- #
- # standard init.
- modname = self.get_module_name()
- prnt('PyMODINIT_FUNC')
- prnt('init%s(void)' % modname)
- prnt('{')
- prnt(' PyObject *lib;')
- prnt(' lib = Py_InitModule("%s", _cffi_methods);' % modname)
- prnt(' if (lib == NULL || %s < 0)' % (
- self._chained_list_constants[False],))
- prnt(' return;')
- prnt(' _cffi_init();')
- prnt('}')
def _compile_module(self):
# compile this C source
@@ -190,13 +126,9 @@ class Verifier(object):
def _load_library(self):
# XXX review all usages of 'self' here!
- # import it as a new extension module
- try:
- module = imp.load_dynamic(self.get_module_name(),
- self.modulefilename)
- except ImportError, e:
- error = "importing %r: %s" % (self.modulefilename, e)
- raise ffiplatform.VerificationError(error)
+ # import it with the CFFI backend
+ backend = self.ffi._backend
+ module = backend.load_library(self.modulefilename)
#
# call loading_cpy_struct() to get the struct layout inferred by
# the C compiler
@@ -204,10 +136,10 @@ class Verifier(object):
#
# the C code will need the <ctype> objects. Collect them in
# order in a list.
- revmapping = dict([(value, key)
- for (key, value) in self._typesdict.items()])
- lst = [revmapping[i] for i in range(len(revmapping))]
- lst = map(self.ffi._get_cached_btype, lst)
+ #revmapping = dict([(value, key)
+ # for (key, value) in self._typesdict.items()])
+ #lst = [revmapping[i] for i in range(len(revmapping))]
+ #lst = map(self.ffi._get_cached_btype, lst)
#
# build the FFILibrary class and instance and call _cffi_setup().
# this will set up some fields like '_cffi_types', and only then
@@ -215,9 +147,9 @@ class Verifier(object):
# build (notably) the constant objects, as <cdata> if they are
# pointers, and store them as attributes on the 'library' object.
class FFILibrary(object):
- pass
+ _cffi_module = module
library = FFILibrary()
- module._cffi_setup(lst, ffiplatform.VerificationError, library)
+ #module._cffi_setup(lst, ffiplatform.VerificationError, library)
#
# finally, call the loaded_cpy_xxx() functions. This will perform
# the final adjustments, like copying the Python->C wrapper
@@ -250,171 +182,85 @@ class Verifier(object):
pass
# ----------
-
- def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode):
- extraarg = ''
- if isinstance(tp, model.PrimitiveType):
- converter = '_cffi_to_c_%s' % (tp.name.replace(' ', '_'),)
- errvalue = '-1'
- #
- elif isinstance(tp, model.PointerType):
- if (isinstance(tp.totype, model.PrimitiveType) and
- tp.totype.name == 'char'):
- converter = '_cffi_to_c_char_p'
- else:
- converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('')
- extraarg = ', _cffi_type(%d)' % self._gettypenum(tp)
- errvalue = 'NULL'
- #
- elif isinstance(tp, (model.StructOrUnion, model.EnumType)):
- # a struct (not a struct pointer) as a function argument
- self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)'
- % (tovar, self._gettypenum(tp), fromvar))
- self._prnt(' %s;' % errcode)
- return
- #
- elif isinstance(tp, model.FunctionPtrType):
- converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('')
- extraarg = ', _cffi_type(%d)' % self._gettypenum(tp)
- errvalue = 'NULL'
- #
- else:
- raise NotImplementedError(tp)
- #
- self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg))
- self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % (
- tovar, tp.get_c_name(''), errvalue))
- self._prnt(' %s;' % errcode)
-
- def _convert_expr_from_c(self, tp, var):
- if isinstance(tp, model.PrimitiveType):
- return '_cffi_from_c_%s(%s)' % (tp.name.replace(' ', '_'), var)
- elif isinstance(tp, (model.PointerType, model.FunctionPtrType)):
- return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
- var, self._gettypenum(tp))
- elif isinstance(tp, model.ArrayType):
- return '_cffi_from_c_deref((char *)%s, _cffi_type(%d))' % (
- var, self._gettypenum(tp))
- elif isinstance(tp, model.StructType):
- return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % (
- var, self._gettypenum(tp))
- elif isinstance(tp, model.EnumType):
- return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % (
- var, self._gettypenum(tp))
- else:
- raise NotImplementedError(tp)
-
- # ----------
# typedefs: generates no code so far
- _generate_cpy_typedef_collecttype = _generate_nothing
_generate_cpy_typedef_decl = _generate_nothing
- _generate_cpy_typedef_method = _generate_nothing
_loading_cpy_typedef = _loaded_noop
_loaded_cpy_typedef = _loaded_noop
# ----------
# function declarations
- def _generate_cpy_function_collecttype(self, tp, name):
- assert isinstance(tp, model.FunctionPtrType)
- if tp.ellipsis:
- self._do_collect_type(tp)
- else:
- for type in tp.args:
- self._do_collect_type(type)
- self._do_collect_type(tp.result)
-
def _generate_cpy_function_decl(self, tp, name):
assert isinstance(tp, model.FunctionPtrType)
if tp.ellipsis:
# cannot support vararg functions better than this: check for its
# exact type (including the fixed arguments), and build it as a
- # constant function pointer (no CPython wrapper)
+ # constant function pointer (no _cffi_f_%s wrapper)
self._generate_cpy_const(False, name, tp)
return
prnt = self._prnt
numargs = len(tp.args)
- if numargs == 0:
- argname = 'no_arg'
- elif numargs == 1:
- argname = 'arg0'
- else:
- argname = 'args'
- prnt('static PyObject *')
- prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname))
+ argnames = []
+ for i, type in enumerate(tp.args):
+ indirection = ''
+ if isinstance(type, model.StructOrUnion):
+ indirection = '*'
+ argnames.append('%sx%d' % (indirection, i))
+ arglist = [type.get_c_name(' %s' % arg)
+ for type, arg in zip(tp.args, argnames)]
+ arglist = ', '.join(arglist) or 'void'
+ funcdecl = ' _cffi_f_%s(%s)' % (name, arglist)
+ prnt(tp.result.get_c_name(funcdecl))
prnt('{')
#
- for i, type in enumerate(tp.args):
- prnt(' %s;' % type.get_c_name(' x%d' % i))
if not isinstance(tp.result, model.VoidType):
- result_code = 'result = '
- prnt(' %s;' % tp.result.get_c_name(' result'))
+ result_code = 'return '
else:
result_code = ''
- #
- if len(tp.args) > 1:
- rng = range(len(tp.args))
- for i in rng:
- prnt(' PyObject *arg%d;' % i)
- prnt()
- prnt(' if (!PyArg_ParseTuple(args, "%s:%s", %s))' % (
- 'O' * numargs, name, ', '.join(['&arg%d' % i for i in rng])))
- prnt(' return NULL;')
- prnt()
- #
- for i, type in enumerate(tp.args):
- self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i,
- 'return NULL')
- prnt()
- #
- prnt(' _cffi_restore_errno();')
- prnt(' { %s%s(%s); }' % (
- result_code, name,
- ', '.join(['x%d' % i for i in range(len(tp.args))])))
- prnt(' _cffi_save_errno();')
- prnt()
- #
- if result_code:
- prnt(' return %s;' %
- self._convert_expr_from_c(tp.result, 'result'))
- else:
- prnt(' Py_INCREF(Py_None);')
- prnt(' return Py_None;')
+ prnt(' %s%s(%s);' % (result_code, name, ', '.join(argnames)))
prnt('}')
prnt()
- def _generate_cpy_function_method(self, tp, name):
- if tp.ellipsis:
- return
- numargs = len(tp.args)
- if numargs == 0:
- meth = 'METH_NOARGS'
- elif numargs == 1:
- meth = 'METH_O'
- else:
- meth = 'METH_VARARGS'
- self._prnt(' {"%s", _cffi_f_%s, %s},' % (name, name, meth))
-
_loading_cpy_function = _loaded_noop
def _loaded_cpy_function(self, tp, name, module, library):
+ assert isinstance(tp, model.FunctionPtrType)
if tp.ellipsis:
- return
- setattr(library, name, getattr(module, name))
+ newfunction = self._load_constant(False, tp, name, module)
+ else:
+ indirections = []
+ if any(isinstance(type, model.StructOrUnion) for type in tp.args):
+ indirect_args = []
+ for i, type in enumerate(tp.args):
+ if isinstance(type, model.StructOrUnion):
+ type = model.PointerType(type)
+ indirections.append((i, type))
+ indirect_args.append(type)
+ tp = model.FunctionPtrType(tuple(indirect_args),
+ tp.result, tp.ellipsis)
+ BFunc = self.ffi._get_cached_btype(tp)
+ wrappername = '_cffi_f_%s' % name
+ newfunction = module.load_function(BFunc, wrappername)
+ for i, type in indirections:
+ newfunction = self._make_struct_wrapper(newfunction, i, type)
+ setattr(library, name, newfunction)
+
+ def _make_struct_wrapper(self, oldfunc, i, tp):
+ backend = self.ffi._backend
+ BType = self.ffi._get_cached_btype(tp)
+ def newfunc(*args):
+ args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:]
+ return oldfunc(*args)
+ return newfunc
# ----------
# named structs
- _generate_cpy_struct_collecttype = _generate_nothing
-
def _generate_cpy_struct_decl(self, tp, name):
assert name == tp.name
self._generate_struct_or_union_decl(tp, 'struct', name)
- def _generate_cpy_struct_method(self, tp, name):
- self._generate_struct_or_union_method(tp, 'struct', name)
-
def _loading_cpy_struct(self, tp, name, module):
self._loading_struct_or_union(tp, 'struct', name, module)
@@ -446,20 +292,19 @@ class Verifier(object):
prnt(' { %s = &p->%s; (void)tmp; }' % (
ftype.get_c_name('(*tmp)'), fname))
prnt('}')
- prnt('static PyObject *')
- prnt('%s(PyObject *self, PyObject *noarg)' % (layoutfuncname,))
+ prnt('ssize_t %s(ssize_t i)' % (layoutfuncname,))
prnt('{')
prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname)
if tp.partial:
- prnt(' static Py_ssize_t nums[] = {')
- prnt(' sizeof(%s),' % cname)
+ prnt(' static ssize_t nums[] = {')
+ prnt(' 1, sizeof(%s),' % cname)
prnt(' offsetof(struct _cffi_aligncheck, y),')
for fname in tp.fldnames:
prnt(' offsetof(%s, %s),' % (cname, fname))
prnt(' sizeof(((%s *)0)->%s),' % (cname, fname))
prnt(' -1')
prnt(' };')
- prnt(' return _cffi_get_struct_layout(nums);')
+ prnt(' return nums[i];')
else:
ffi = self.ffi
BStruct = ffi._get_cached_btype(tp)
@@ -478,43 +323,42 @@ class Verifier(object):
for i in range(1, len(conditions)-1):
prnt(' %s ||' % conditions[i])
prnt(' %s) {' % conditions[-1])
- prnt(' Py_INCREF(Py_False);')
- prnt(' return Py_False;')
+ prnt(' return -1;')
prnt(' }')
prnt(' else {')
- prnt(' Py_INCREF(Py_True);')
- prnt(' return Py_True;')
+ prnt(' return 0;')
prnt(' }')
prnt(' /* the next line is not executed, but compiled */')
prnt(' %s(0);' % (checkfuncname,))
prnt('}')
prnt()
- def _generate_struct_or_union_method(self, tp, prefix, name):
- if tp.fldnames is None:
- return # nothing to do with opaque structs
- layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
- self._prnt(' {"%s", %s, METH_NOARGS},' % (layoutfuncname,
- layoutfuncname))
-
def _loading_struct_or_union(self, tp, prefix, name, module):
if tp.fldnames is None:
return # nothing to do with opaque structs
layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
cname = ('%s %s' % (prefix, name)).strip()
#
- function = getattr(module, layoutfuncname)
- layout = function()
- if layout is False:
+ BFunc = self.ffi.typeof("ssize_t(*)(ssize_t)")
+ function = module.load_function(BFunc, layoutfuncname)
+ layout = function(0)
+ if layout < 0:
raise ffiplatform.VerificationError(
"incompatible layout for %s" % cname)
- elif layout is True:
+ elif layout == 0:
assert not tp.partial
else:
- totalsize = layout[0]
- totalalignment = layout[1]
- fieldofs = layout[2::2]
- fieldsize = layout[3::2]
+ totalsize = function(1)
+ totalalignment = function(2)
+ fieldofs = []
+ fieldsize = []
+ num = 3
+ while True:
+ x = function(num)
+ if x < 0: break
+ fieldofs.append(x)
+ fieldsize.append(function(num+1))
+ num += 2
assert len(fieldofs) == len(fieldsize) == len(tp.fldnames)
tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment
@@ -527,14 +371,9 @@ class Verifier(object):
# 'anonymous' declarations. These are produced for anonymous structs
# or unions; the 'name' is obtained by a typedef.
- _generate_cpy_anonymous_collecttype = _generate_nothing
-
def _generate_cpy_anonymous_decl(self, tp, name):
self._generate_struct_or_union_decl(tp, '', name)
- def _generate_cpy_anonymous_method(self, tp, name):
- self._generate_struct_or_union_method(tp, '', name)
-
def _loading_cpy_anonymous(self, tp, name, module):
self._loading_struct_or_union(tp, '', name, module)
@@ -544,58 +383,54 @@ class Verifier(object):
# ----------
# constants, likely declared with '#define'
- def _generate_cpy_const(self, is_int, name, tp=None, category='const',
- vartp=None, delayed=True):
+ def _generate_cpy_const(self, is_int, name, tp=None, category='const'):
prnt = self._prnt
funcname = '_cffi_%s_%s' % (category, name)
- prnt('static int %s(PyObject *lib)' % funcname)
- prnt('{')
- prnt(' PyObject *o;')
- prnt(' int res;')
- if not is_int:
- prnt(' %s;' % (vartp or tp).get_c_name(' i'))
- else:
+ if is_int:
assert category == 'const'
- #
- if not is_int:
+ prnt('int %s(long long *out_value)' % funcname)
+ prnt('{')
+ prnt(' *out_value = (long long)(%s);' % (name,))
+ prnt(' return (%s) <= 0;' % (name,))
+ prnt('}')
+ else:
+ assert tp is not None
+ prnt(tp.get_c_name(' %s(void)' % funcname),)
+ prnt('{')
if category == 'var':
- realexpr = '&' + name
+ ampersand = '&'
else:
- realexpr = name
- prnt(' i = (%s);' % (realexpr,))
- prnt(' o = %s;' % (self._convert_expr_from_c(tp, 'i'),))
- assert delayed
- else:
- prnt(' if (LONG_MIN <= (%s) && (%s) <= LONG_MAX)' % (name, name))
- prnt(' o = PyInt_FromLong((long)(%s));' % (name,))
- prnt(' else if ((%s) <= 0)' % (name,))
- prnt(' o = PyLong_FromLongLong((long long)(%s));' % (name,))
- prnt(' else')
- prnt(' o = PyLong_FromUnsignedLongLong('
- '(unsigned long long)(%s));' % (name,))
- prnt(' if (o == NULL)')
- prnt(' return -1;')
- prnt(' res = PyObject_SetAttrString(lib, "%s", o);' % name)
- prnt(' Py_DECREF(o);')
- prnt(' if (res < 0)')
- prnt(' return -1;')
- prnt(' return %s;' % self._chained_list_constants[delayed])
- self._chained_list_constants[delayed] = funcname + '(lib)'
- prnt('}')
+ ampersand = ''
+ prnt(' return (%s%s);' % (ampersand, name))
+ prnt('}')
prnt()
- def _generate_cpy_constant_collecttype(self, tp, name):
- is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
- if not is_int:
- self._do_collect_type(tp)
-
def _generate_cpy_constant_decl(self, tp, name):
is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
self._generate_cpy_const(is_int, name, tp)
- _generate_cpy_constant_method = _generate_nothing
_loading_cpy_constant = _loaded_noop
- _loaded_cpy_constant = _loaded_noop
+
+ def _load_constant(self, is_int, tp, name, module):
+ funcname = '_cffi_const_%s' % name
+ if is_int:
+ BFunc = self.ffi.typeof("int(*)(long long*)")
+ function = module.load_function(BFunc, funcname)
+ p = self.ffi.new("long long*")
+ negative = function(p)
+ value = int(p[0])
+ if value < 0 and not negative:
+ value += (1 << (8*self.ffi.sizeof("long long")))
+ else:
+ BFunc = self.ffi.typeof(tp.get_c_name('(*)(void)'))
+ function = module.load_function(BFunc, funcname)
+ value = function()
+ return value
+
+ def _loaded_cpy_constant(self, tp, name, module, library):
+ is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
+ value = self._load_constant(is_int, tp, name, module)
+ setattr(library, name, value)
# ----------
# enums
@@ -603,37 +438,40 @@ class Verifier(object):
def _generate_cpy_enum_decl(self, tp, name):
if tp.partial:
for enumerator in tp.enumerators:
- self._generate_cpy_const(True, enumerator, delayed=False)
+ self._generate_cpy_const(True, enumerator)
return
#
funcname = '_cffi_enum_%s' % name
prnt = self._prnt
- prnt('static int %s(PyObject *lib)' % funcname)
+ prnt('int %s(char *out_error)' % funcname)
prnt('{')
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
prnt(' if (%s != %d) {' % (enumerator, enumvalue))
- prnt(' PyErr_Format(_cffi_VerificationError,')
- prnt(' "in enum %s: %s has the real value %d, '
- 'not %d",')
- prnt(' "%s", "%s", (int)%s, %d);' % (
+ prnt(' snprintf(out_error, 255, "in enum %s: '
+ '%s has the real value %d, not %d",')
+ prnt(' "%s", "%s", (int)%s, %d);' % (
name, enumerator, enumerator, enumvalue))
prnt(' return -1;')
prnt(' }')
- prnt(' return %s;' % self._chained_list_constants[True])
- self._chained_list_constants[True] = funcname + '(lib)'
+ prnt(' return 0;')
prnt('}')
prnt()
- _generate_cpy_enum_collecttype = _generate_nothing
- _generate_cpy_enum_method = _generate_nothing
_loading_cpy_enum = _loaded_noop
def _loading_cpy_enum(self, tp, name, module):
if tp.partial:
- enumvalues = [getattr(module, enumerator)
+ enumvalues = [self._load_constant(True, tp, enumerator, module)
for enumerator in tp.enumerators]
tp.enumvalues = tuple(enumvalues)
tp.partial = False
+ else:
+ BFunc = self.ffi.typeof("int(*)(char*)")
+ funcname = '_cffi_enum_%s' % name
+ function = module.load_function(BFunc, funcname)
+ p = self.ffi.new("char[]", 256)
+ if function(p) < 0:
+ raise ffiplatform.VerificationError(str(p))
def _loaded_cpy_enum(self, tp, name, module, library):
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
@@ -646,185 +484,51 @@ class Verifier(object):
assert tp == '...'
self._generate_cpy_const(True, name)
- _generate_cpy_macro_collecttype = _generate_nothing
- _generate_cpy_macro_method = _generate_nothing
_loading_cpy_macro = _loaded_noop
- _loaded_cpy_macro = _loaded_noop
+
+ def _loaded_cpy_macro(self, tp, name, module, library):
+ value = self._load_constant(True, tp, name, module)
+ setattr(library, name, value)
# ----------
# global variables
- def _generate_cpy_variable_collecttype(self, tp, name):
- if isinstance(tp, model.ArrayType):
- self._do_collect_type(tp)
- else:
- tp_ptr = model.PointerType(tp)
- self._do_collect_type(tp_ptr)
-
def _generate_cpy_variable_decl(self, tp, name):
if isinstance(tp, model.ArrayType):
tp_ptr = model.PointerType(tp.item)
- self._generate_cpy_const(False, name, tp, vartp=tp_ptr)
+ self._generate_cpy_const(False, name, tp_ptr)
else:
tp_ptr = model.PointerType(tp)
self._generate_cpy_const(False, name, tp_ptr, category='var')
- _generate_cpy_variable_method = _generate_nothing
_loading_cpy_variable = _loaded_noop
def _loaded_cpy_variable(self, tp, name, module, library):
if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the
- return # sense that "a=..." is forbidden
+ # sense that "a=..." is forbidden
+ tp_ptr = model.PointerType(tp.item)
+ value = self._load_constant(False, tp_ptr, name, module)
+ setattr(library, name, value)
+ return
# remove ptr=<cdata 'int *'> from the library instance, and replace
# it by a property on the class, which reads/writes into ptr[0].
- ptr = getattr(library, name)
- delattr(library, name)
+ funcname = '_cffi_var_%s' % name
+ BFunc = self.ffi.typeof(tp.get_c_name('*(*)(void)'))
+ function = module.load_function(BFunc, funcname)
+ ptr = function()
def getter(library):
return ptr[0]
def setter(library, value):
ptr[0] = value
setattr(library.__class__, name, property(getter, setter))
- # ----------
-
- def _generate_setup_custom(self):
- prnt = self._prnt
- prnt('static PyObject *_cffi_setup_custom(PyObject *lib)')
- prnt('{')
- prnt(' if (%s < 0)' % self._chained_list_constants[True])
- prnt(' return NULL;')
- prnt(' Py_INCREF(Py_None);')
- prnt(' return Py_None;')
- prnt('}')
-
cffimod_header = r'''
-#include <Python.h>
+#include <stdio.h>
#include <stddef.h>
-
-#define _cffi_from_c_double PyFloat_FromDouble
-#define _cffi_from_c_float PyFloat_FromDouble
-#define _cffi_from_c_signed_char PyInt_FromLong
-#define _cffi_from_c_short PyInt_FromLong
-#define _cffi_from_c_int PyInt_FromLong
-#define _cffi_from_c_long PyInt_FromLong
-#define _cffi_from_c_unsigned_char PyInt_FromLong
-#define _cffi_from_c_unsigned_short PyInt_FromLong
-#define _cffi_from_c_unsigned_long PyLong_FromUnsignedLong
-#define _cffi_from_c_unsigned_long_long PyLong_FromUnsignedLongLong
-
-#if SIZEOF_INT < SIZEOF_LONG
-# define _cffi_from_c_unsigned_int PyInt_FromLong
-#else
-# define _cffi_from_c_unsigned_int PyLong_FromUnsignedLong
-#endif
-
-#if SIZEOF_LONG < SIZEOF_LONG_LONG
-# define _cffi_from_c_long_long PyLong_FromLongLong
-#else
-# define _cffi_from_c_long_long PyInt_FromLong
-#endif
-
-#define _cffi_to_c_long PyInt_AsLong
-#define _cffi_to_c_double PyFloat_AsDouble
-#define _cffi_to_c_float PyFloat_AsDouble
-
-#define _cffi_to_c_char_p \
- ((char *(*)(PyObject *))_cffi_exports[0])
-#define _cffi_to_c_signed_char \
- ((signed char(*)(PyObject *))_cffi_exports[1])
-#define _cffi_to_c_unsigned_char \
- ((unsigned char(*)(PyObject *))_cffi_exports[2])
-#define _cffi_to_c_short \
- ((short(*)(PyObject *))_cffi_exports[3])
-#define _cffi_to_c_unsigned_short \
- ((unsigned short(*)(PyObject *))_cffi_exports[4])
-
-#if SIZEOF_INT < SIZEOF_LONG
-# define _cffi_to_c_int \
- ((int(*)(PyObject *))_cffi_exports[5])
-# define _cffi_to_c_unsigned_int \
- ((unsigned int(*)(PyObject *))_cffi_exports[6])
-#else
-# define _cffi_to_c_int _cffi_to_c_long
-# define _cffi_to_c_unsigned_int _cffi_to_c_unsigned_long
-#endif
-
-#define _cffi_to_c_unsigned_long \
- ((unsigned long(*)(PyObject *))_cffi_exports[7])
-#define _cffi_to_c_unsigned_long_long \
- ((unsigned long long(*)(PyObject *))_cffi_exports[8])
-#define _cffi_to_c_char \
- ((char(*)(PyObject *))_cffi_exports[9])
-#define _cffi_from_c_pointer \
- ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10])
-#define _cffi_to_c_pointer \
- ((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11])
-#define _cffi_get_struct_layout \
- ((PyObject *(*)(Py_ssize_t[]))_cffi_exports[12])
-#define _cffi_restore_errno \
- ((void(*)(void))_cffi_exports[13])
-#define _cffi_save_errno \
- ((void(*)(void))_cffi_exports[14])
-#define _cffi_from_c_char \
- ((PyObject *(*)(char))_cffi_exports[15])
-#define _cffi_from_c_deref \
- ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16])
-#define _cffi_to_c \
- ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17])
-#define _cffi_from_c_struct \
- ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18])
-#define _cffi_to_c_wchar_t \
- ((wchar_t(*)(PyObject *))_cffi_exports[19])
-#define _cffi_from_c_wchar_t \
- ((PyObject *(*)(wchar_t))_cffi_exports[20])
-#define _CFFI_NUM_EXPORTS 21
-
-#if SIZEOF_LONG < SIZEOF_LONG_LONG
-# define _cffi_to_c_long_long PyLong_AsLongLong
-#else
-# define _cffi_to_c_long_long _cffi_to_c_long
-#endif
-
-typedef struct _ctypedescr CTypeDescrObject;
-
-static void *_cffi_exports[_CFFI_NUM_EXPORTS];
-static PyObject *_cffi_types, *_cffi_VerificationError;
-
-static PyObject *_cffi_setup_custom(PyObject *lib); /* forward */
-
-static PyObject *_cffi_setup(PyObject *self, PyObject *args)
-{
- PyObject *library;
- if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError,
- &library))
- return NULL;
- Py_INCREF(_cffi_types);
- Py_INCREF(_cffi_VerificationError);
- return _cffi_setup_custom(library);
-}
-
-static void _cffi_init(void)
-{
- PyObject *module = PyImport_ImportModule("_cffi_backend");
- PyObject *c_api_object;
-
- if (module == NULL)
- return;
-
- c_api_object = PyObject_GetAttrString(module, "_C_API");
- if (c_api_object == NULL)
- return;
- if (!PyCObject_Check(c_api_object)) {
- PyErr_SetNone(PyExc_ImportError);
- return;
- }
- memcpy(_cffi_exports, PyCObject_AsVoidPtr(c_api_object),
- _CFFI_NUM_EXPORTS * sizeof(void *));
-}
-
-#define _cffi_type(num) ((CTypeDescrObject *)PyList_GET_ITEM(_cffi_types, num))
-
-/**********/
+#include <stdint.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/types.h> /* XXX for ssize_t */
'''
# ____________________________________________________________