[pypy-commit] pypy cffi-stdcall: Pass around the abi of functions, and use it to write "__stdcall" in the repr
arigo
noreply at buildbot.pypy.org
Wed Oct 7 09:43:15 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-stdcall
Changeset: r80011:670a38662272
Date: 2015-10-07 09:43 +0200
http://bitbucket.org/pypy/pypy/changeset/670a38662272/
Log: Pass around the abi of functions, and use it to write "__stdcall" in
the repr
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -1,9 +1,16 @@
import sys
from pypy.interpreter.mixedmodule import MixedModule
-from rpython.rlib import rdynload
+from rpython.rlib import rdynload, clibffi
VERSION = "1.3.0"
+FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
+try:
+ FFI_STDCALL = clibffi.FFI_STDCALL
+ has_stdcall = True
+except AttributeError:
+ has_stdcall = False
+
class Module(MixedModule):
@@ -44,8 +51,8 @@
'get_errno': 'cerrno.get_errno',
'set_errno': 'cerrno.set_errno',
- 'FFI_DEFAULT_ABI': 'ctypefunc._get_abi(space, "FFI_DEFAULT_ABI")',
- 'FFI_CDECL': 'ctypefunc._get_abi(space,"FFI_DEFAULT_ABI")',#win32 name
+ 'FFI_DEFAULT_ABI': 'space.wrap(%d)' % FFI_DEFAULT_ABI,
+ 'FFI_CDECL': 'space.wrap(%d)' % FFI_DEFAULT_ABI, # win32 name
# CFFI 1.0
'FFI': 'ffi_obj.W_FFIObject',
@@ -53,6 +60,9 @@
if sys.platform == 'win32':
interpleveldefs['getwinerror'] = 'cerrno.getwinerror'
+ if has_stdcall:
+ interpleveldefs['FFI_STDCALL'] = 'space.wrap(%d)' % FFI_STDCALL
+
def get_dict_rtld_constants():
found = {}
diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -12,6 +12,7 @@
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
from pypy.interpreter.error import OperationError, oefmt
+from pypy.module import _cffi_backend
from pypy.module._cffi_backend import ctypearray, cdataobj, cerrno
from pypy.module._cffi_backend.ctypeobj import W_CType
from pypy.module._cffi_backend.ctypeptr import W_CTypePtrBase, W_CTypePointer
@@ -23,20 +24,21 @@
class W_CTypeFunc(W_CTypePtrBase):
- _attrs_ = ['fargs', 'ellipsis', 'cif_descr']
- _immutable_fields_ = ['fargs[*]', 'ellipsis', 'cif_descr']
+ _attrs_ = ['fargs', 'ellipsis', 'abi', 'cif_descr']
+ _immutable_fields_ = ['fargs[*]', 'ellipsis', 'abi', 'cif_descr']
kind = "function"
cif_descr = lltype.nullptr(CIF_DESCRIPTION)
- def __init__(self, space, fargs, fresult, ellipsis):
+ def __init__(self, space, fargs, fresult, ellipsis, abi):
assert isinstance(ellipsis, bool)
- extra = self._compute_extra_text(fargs, fresult, ellipsis)
+ extra, xpos = self._compute_extra_text(fargs, fresult, ellipsis, abi)
size = rffi.sizeof(rffi.VOIDP)
- W_CTypePtrBase.__init__(self, space, size, extra, 2, fresult,
+ W_CTypePtrBase.__init__(self, space, size, extra, xpos, fresult,
could_cast_anything=False)
self.fargs = fargs
self.ellipsis = ellipsis
+ self.abi = abi
# fresult is stored in self.ctitem
if not ellipsis:
@@ -44,7 +46,7 @@
# at all. The cif is computed on every call from the actual
# types passed in. For all other functions, the cif_descr
# is computed here.
- builder = CifDescrBuilder(fargs, fresult)
+ builder = CifDescrBuilder(fargs, fresult, abi)
try:
builder.rawallocate(self)
except OperationError, e:
@@ -76,7 +78,7 @@
ctypefunc.fargs = fvarargs
ctypefunc.ctitem = self.ctitem
#ctypefunc.cif_descr = NULL --- already provided as the default
- CifDescrBuilder(fvarargs, self.ctitem).rawallocate(ctypefunc)
+ CifDescrBuilder(fvarargs, self.ctitem, self.abi).rawallocate(ctypefunc)
return ctypefunc
@rgc.must_be_light_finalizer
@@ -84,8 +86,13 @@
if self.cif_descr:
lltype.free(self.cif_descr, flavor='raw')
- def _compute_extra_text(self, fargs, fresult, ellipsis):
+ def _compute_extra_text(self, fargs, fresult, ellipsis, abi):
+ from pypy.module._cffi_backend import newtype
argnames = ['(*)(']
+ xpos = 2
+ if _cffi_backend.has_stdcall and abi == _cffi_backend.FFI_STDCALL:
+ argnames[0] = '(__stdcall *)('
+ xpos += len('__stdcall ')
for i, farg in enumerate(fargs):
if i > 0:
argnames.append(', ')
@@ -95,7 +102,7 @@
argnames.append(', ')
argnames.append('...')
argnames.append(')')
- return ''.join(argnames)
+ return ''.join(argnames), xpos
def _fget(self, attrchar):
if attrchar == 'a': # args
@@ -106,7 +113,7 @@
if attrchar == 'E': # ellipsis
return self.space.wrap(self.ellipsis)
if attrchar == 'A': # abi
- return self.space.wrap(clibffi.FFI_DEFAULT_ABI) # XXX
+ return self.space.wrap(self.abi)
return W_CTypePtrBase._fget(self, attrchar)
def call(self, funcaddr, args_w):
@@ -181,11 +188,6 @@
def set_mustfree_flag(data, flag):
rffi.ptradd(data, -1)[0] = chr(flag)
-def _get_abi(space, name):
- abi = getattr(clibffi, name)
- assert isinstance(abi, int)
- return space.wrap(abi)
-
# ____________________________________________________________
@@ -260,9 +262,10 @@
class CifDescrBuilder(object):
rawmem = lltype.nullptr(rffi.CCHARP.TO)
- def __init__(self, fargs, fresult):
+ def __init__(self, fargs, fresult, fabi):
self.fargs = fargs
self.fresult = fresult
+ self.fabi = fabi
def fb_alloc(self, size):
size = llmemory.raw_malloc_usage(size)
@@ -421,7 +424,7 @@
cif_descr.exchange_size = exchange_offset
def fb_extra_fields(self, cif_descr):
- cif_descr.abi = clibffi.FFI_DEFAULT_ABI # XXX
+ cif_descr.abi = self.fabi
cif_descr.nargs = len(self.fargs)
cif_descr.rtype = self.rtype
cif_descr.atypes = self.atypes
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -4,10 +4,11 @@
from rpython.rlib.objectmodel import specialize, r_dict, compute_identity_hash
from rpython.rlib.rarithmetic import ovfcheck, intmask
-from rpython.rlib import jit, rweakref
+from rpython.rlib import jit, rweakref, clibffi
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rtyper.tool import rffi_platform
+from pypy.module import _cffi_backend
from pypy.module._cffi_backend import (ctypeobj, ctypeprim, ctypeptr,
ctypearray, ctypestruct, ctypevoid, ctypeenum)
@@ -592,8 +593,9 @@
# ____________________________________________________________
- at unwrap_spec(w_fresult=ctypeobj.W_CType, ellipsis=int)
-def new_function_type(space, w_fargs, w_fresult, ellipsis=0):
+ at unwrap_spec(w_fresult=ctypeobj.W_CType, ellipsis=int, abi=int)
+def new_function_type(space, w_fargs, w_fresult, ellipsis=0,
+ abi=_cffi_backend.FFI_DEFAULT_ABI):
fargs = []
for w_farg in space.fixedview(w_fargs):
if not isinstance(w_farg, ctypeobj.W_CType):
@@ -602,28 +604,28 @@
if isinstance(w_farg, ctypearray.W_CTypeArray):
w_farg = w_farg.ctptr
fargs.append(w_farg)
- return _new_function_type(space, fargs, w_fresult, bool(ellipsis))
+ return _new_function_type(space, fargs, w_fresult, bool(ellipsis), abi)
-def _func_key_hash(unique_cache, fargs, fresult, ellipsis):
+def _func_key_hash(unique_cache, fargs, fresult, ellipsis, abi):
x = compute_identity_hash(fresult)
for w_arg in fargs:
y = compute_identity_hash(w_arg)
x = intmask((1000003 * x) ^ y)
- x ^= ellipsis
+ x ^= (ellipsis - abi)
if unique_cache.for_testing: # constant-folded to False in translation;
x &= 3 # but for test, keep only 2 bits of hash
return x
# can't use @jit.elidable here, because it might call back to random
# space functions via force_lazy_struct()
-def _new_function_type(space, fargs, fresult, ellipsis=False):
+def _new_function_type(space, fargs, fresult, ellipsis, abi):
try:
- return _get_function_type(space, fargs, fresult, ellipsis)
+ return _get_function_type(space, fargs, fresult, ellipsis, abi)
except KeyError:
- return _build_function_type(space, fargs, fresult, ellipsis)
+ return _build_function_type(space, fargs, fresult, ellipsis, abi)
@jit.elidable
-def _get_function_type(space, fargs, fresult, ellipsis):
+def _get_function_type(space, fargs, fresult, ellipsis, abi):
# This function is elidable because if called again with exactly the
# same arguments (and if it didn't raise KeyError), it would give
# the same result, at least as long as this result is still live.
@@ -633,18 +635,19 @@
# one such dict, but in case of hash collision, there might be
# more.
unique_cache = space.fromcache(UniqueCache)
- func_hash = _func_key_hash(unique_cache, fargs, fresult, ellipsis)
+ func_hash = _func_key_hash(unique_cache, fargs, fresult, ellipsis, abi)
for weakdict in unique_cache.functions:
ctype = weakdict.get(func_hash)
if (ctype is not None and
ctype.ctitem is fresult and
ctype.fargs == fargs and
- ctype.ellipsis == ellipsis):
+ ctype.ellipsis == ellipsis and
+ ctype.abi == abi):
return ctype
raise KeyError
@jit.dont_look_inside
-def _build_function_type(space, fargs, fresult, ellipsis):
+def _build_function_type(space, fargs, fresult, ellipsis, abi):
from pypy.module._cffi_backend import ctypefunc
#
if ((fresult.size < 0 and
@@ -658,9 +661,9 @@
raise oefmt(space.w_TypeError,
"invalid result type: '%s'", fresult.name)
#
- fct = ctypefunc.W_CTypeFunc(space, fargs, fresult, ellipsis)
+ fct = ctypefunc.W_CTypeFunc(space, fargs, fresult, ellipsis, abi)
unique_cache = space.fromcache(UniqueCache)
- func_hash = _func_key_hash(unique_cache, fargs, fresult, ellipsis)
+ func_hash = _func_key_hash(unique_cache, fargs, fresult, ellipsis, abi)
for weakdict in unique_cache.functions:
if weakdict.get(func_hash) is None:
weakdict.set(func_hash, fct)
More information about the pypy-commit
mailing list