[pypy-commit] pypy release-1.9.x: merge default
fijal
noreply at buildbot.pypy.org
Tue Jun 5 15:01:07 CEST 2012
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: release-1.9.x
Changeset: r55411:8bd9e16aa775
Date: 2012-06-05 15:00 +0200
http://bitbucket.org/pypy/pypy/changeset/8bd9e16aa775/
Log: merge default
diff --git a/lib-python/2.7/ctypes/__init__.py b/lib-python/2.7/ctypes/__init__.py
--- a/lib-python/2.7/ctypes/__init__.py
+++ b/lib-python/2.7/ctypes/__init__.py
@@ -351,7 +351,10 @@
self._FuncPtr = _FuncPtr
if handle is None:
- self._handle = _ffi.CDLL(name, mode)
+ if flags & _FUNCFLAG_CDECL:
+ self._handle = _ffi.CDLL(name, mode)
+ else:
+ self._handle = _ffi.WinDLL(name, mode)
else:
self._handle = handle
diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
--- a/lib_pypy/_ctypes/function.py
+++ b/lib_pypy/_ctypes/function.py
@@ -391,7 +391,7 @@
address = self._get_address()
ffiargs = [argtype.get_ffi_argtype() for argtype in argtypes]
ffires = restype.get_ffi_argtype()
- return _ffi.FuncPtr.fromaddr(address, '', ffiargs, ffires)
+ return _ffi.FuncPtr.fromaddr(address, '', ffiargs, ffires, self._flags_)
def _getfuncptr(self, argtypes, restype, thisarg=None):
if self._ptr is not None and (argtypes is self._argtypes_ or argtypes == self._argtypes_):
@@ -412,7 +412,7 @@
ptr = thisarg[0][self._com_index - 0x1000]
ffiargs = [argtype.get_ffi_argtype() for argtype in argtypes]
ffires = restype.get_ffi_argtype()
- return _ffi.FuncPtr.fromaddr(ptr, '', ffiargs, ffires)
+ return _ffi.FuncPtr.fromaddr(ptr, '', ffiargs, ffires, self._flags_)
cdll = self.dll._handle
try:
diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst
--- a/pypy/doc/cppyy.rst
+++ b/pypy/doc/cppyy.rst
@@ -361,6 +361,11 @@
If a pointer is a global variable, the C++ side can replace the underlying
object and the python side will immediately reflect that.
+* **PyObject***: Arguments and return types of ``PyObject*`` can be used, and
+ passed on to CPython API calls.
+ Since these CPython-like objects need to be created and tracked (this all
+ happens through ``cpyext``) this interface is not particularly fast.
+
* **static data members**: Are represented as python property objects on the
class and the meta-class.
Both read and write access is as expected.
diff --git a/pypy/doc/whatsnew-1.9.rst b/pypy/doc/whatsnew-1.9.rst
--- a/pypy/doc/whatsnew-1.9.rst
+++ b/pypy/doc/whatsnew-1.9.rst
@@ -84,6 +84,8 @@
_invalid_parameter_handler
.. branch: win32-kill
Add os.kill to windows even if translating python does not have os.kill
+.. branch: win_ffi
+Handle calling conventions for the _ffi and ctypes modules
.. branch: win64-stage1
.. branch: zlib-mem-pressure
Memory "leaks" associated with zlib are fixed.
diff --git a/pypy/jit/backend/x86/test/test_ztranslation.py b/pypy/jit/backend/x86/test/test_ztranslation.py
--- a/pypy/jit/backend/x86/test/test_ztranslation.py
+++ b/pypy/jit/backend/x86/test/test_ztranslation.py
@@ -69,7 +69,7 @@
#
from pypy.rpython.lltypesystem import lltype, rffi
from pypy.rlib.libffi import types, CDLL, ArgChain
- from pypy.rlib.test.test_libffi import get_libm_name
+ from pypy.rlib.test.test_clibffi import get_libm_name
libm_name = get_libm_name(sys.platform)
jitdriver2 = JitDriver(greens=[], reds = ['i', 'func', 'res', 'x'])
def libffi_stuff(i, j):
diff --git a/pypy/module/_ffi/__init__.py b/pypy/module/_ffi/__init__.py
--- a/pypy/module/_ffi/__init__.py
+++ b/pypy/module/_ffi/__init__.py
@@ -1,4 +1,5 @@
from pypy.interpreter.mixedmodule import MixedModule
+import os
class Module(MixedModule):
@@ -10,7 +11,8 @@
'_StructDescr': 'interp_struct.W__StructDescr',
'Field': 'interp_struct.W_Field',
}
-
+ if os.name == 'nt':
+ interpleveldefs['WinDLL'] = 'interp_funcptr.W_WinDLL'
appleveldefs = {
'Structure': 'app_struct.Structure',
}
diff --git a/pypy/module/_ffi/interp_funcptr.py b/pypy/module/_ffi/interp_funcptr.py
--- a/pypy/module/_ffi/interp_funcptr.py
+++ b/pypy/module/_ffi/interp_funcptr.py
@@ -9,6 +9,7 @@
#
from pypy.rlib import jit
from pypy.rlib import libffi
+from pypy.rlib.clibffi import get_libc_name, StackCheckError
from pypy.rlib.rdynload import DLOpenError
from pypy.rlib.rarithmetic import intmask, r_uint
from pypy.rlib.objectmodel import we_are_translated
@@ -59,7 +60,10 @@
self = jit.promote(self)
argchain = self.build_argchain(space, args_w)
func_caller = CallFunctionConverter(space, self.func, argchain)
- return func_caller.do_and_wrap(self.w_restype)
+ try:
+ return func_caller.do_and_wrap(self.w_restype)
+ except StackCheckError, e:
+ raise OperationError(space.w_ValueError, space.wrap(e.message))
#return self._do_call(space, argchain)
def free_temp_buffers(self, space):
@@ -230,13 +234,14 @@
restype = unwrap_ffitype(space, w_restype, allow_void=True)
return argtypes_w, argtypes, w_restype, restype
- at unwrap_spec(addr=r_uint, name=str)
-def descr_fromaddr(space, w_cls, addr, name, w_argtypes, w_restype):
+ at unwrap_spec(addr=r_uint, name=str, flags=int)
+def descr_fromaddr(space, w_cls, addr, name, w_argtypes,
+ w_restype, flags=libffi.FUNCFLAG_CDECL):
argtypes_w, argtypes, w_restype, restype = unpack_argtypes(space,
w_argtypes,
w_restype)
addr = rffi.cast(rffi.VOIDP, addr)
- func = libffi.Func(name, argtypes, restype, addr)
+ func = libffi.Func(name, argtypes, restype, addr, flags)
return W_FuncPtr(func, argtypes_w, w_restype)
@@ -254,6 +259,7 @@
class W_CDLL(Wrappable):
def __init__(self, space, name, mode):
+ self.flags = libffi.FUNCFLAG_CDECL
self.space = space
if name is None:
self.name = "<None>"
@@ -271,7 +277,8 @@
w_argtypes,
w_restype)
try:
- func = self.cdll.getpointer(name, argtypes, restype)
+ func = self.cdll.getpointer(name, argtypes, restype,
+ flags = self.flags)
except KeyError:
raise operationerrfmt(space.w_AttributeError,
"No symbol %s found in library %s", name, self.name)
@@ -300,10 +307,26 @@
getaddressindll = interp2app(W_CDLL.getaddressindll),
)
+class W_WinDLL(W_CDLL):
+ def __init__(self, space, name, mode):
+ W_CDLL.__init__(self, space, name, mode)
+ self.flags = libffi.FUNCFLAG_STDCALL
+
+ at unwrap_spec(name='str_or_None', mode=int)
+def descr_new_windll(space, w_type, name, mode=-1):
+ return space.wrap(W_WinDLL(space, name, mode))
+
+
+W_WinDLL.typedef = TypeDef(
+ '_ffi.WinDLL',
+ __new__ = interp2app(descr_new_windll),
+ getfunc = interp2app(W_WinDLL.getfunc),
+ getaddressindll = interp2app(W_WinDLL.getaddressindll),
+ )
+
# ========================================================================
def get_libc(space):
- from pypy.rlib.clibffi import get_libc_name
try:
return space.wrap(W_CDLL(space, get_libc_name(), -1))
except OSError, e:
diff --git a/pypy/module/_ffi/test/test_funcptr.py b/pypy/module/_ffi/test/test_funcptr.py
--- a/pypy/module/_ffi/test/test_funcptr.py
+++ b/pypy/module/_ffi/test/test_funcptr.py
@@ -1,11 +1,11 @@
from pypy.conftest import gettestobjspace
-from pypy.translator.platform import platform
-from pypy.translator.tool.cbuild import ExternalCompilationInfo
-from pypy.module._rawffi.interp_rawffi import TYPEMAP
-from pypy.module._rawffi.tracker import Tracker
-from pypy.translator.platform import platform
+from pypy.rpython.lltypesystem import rffi
+from pypy.rlib.clibffi import get_libc_name
+from pypy.rlib.libffi import types
+from pypy.rlib.libffi import CDLL
+from pypy.rlib.test.test_clibffi import get_libm_name
-import os, sys, py
+import sys, py
class BaseAppTestFFI(object):
@@ -37,9 +37,6 @@
return str(platform.compile([c_file], eci, 'x', standalone=False))
def setup_class(cls):
- from pypy.rpython.lltypesystem import rffi
- from pypy.rlib.libffi import get_libc_name, CDLL, types
- from pypy.rlib.test.test_libffi import get_libm_name
space = gettestobjspace(usemodules=('_ffi', '_rawffi'))
cls.space = space
cls.w_iswin32 = space.wrap(sys.platform == 'win32')
@@ -96,7 +93,7 @@
def test_getaddressindll(self):
import sys
- from _ffi import CDLL, types
+ from _ffi import CDLL
libm = CDLL(self.libm_name)
pow_addr = libm.getaddressindll('pow')
fff = sys.maxint*2-1
@@ -105,7 +102,6 @@
assert pow_addr == self.pow_addr & fff
def test_func_fromaddr(self):
- import sys
from _ffi import CDLL, types, FuncPtr
libm = CDLL(self.libm_name)
pow_addr = libm.getaddressindll('pow')
@@ -569,3 +565,66 @@
skip("unix specific")
libnone = CDLL(None)
raises(AttributeError, "libnone.getfunc('I_do_not_exist', [], types.void)")
+
+ def test_calling_convention1(self):
+ if not self.iswin32:
+ skip("windows specific")
+ from _ffi import WinDLL, types
+ libm = WinDLL(self.libm_name)
+ pow = libm.getfunc('pow', [types.double, types.double], types.double)
+ try:
+ pow(2, 3)
+ except ValueError, e:
+ assert e.message.startswith('Procedure called with')
+ else:
+ assert 0, 'test must assert, wrong calling convention'
+
+ def test_calling_convention2(self):
+ if not self.iswin32:
+ skip("windows specific")
+ from _ffi import WinDLL, types
+ kernel = WinDLL('Kernel32.dll')
+ sleep = kernel.getfunc('Sleep', [types.uint], types.void)
+ sleep(10)
+
+ def test_calling_convention3(self):
+ if not self.iswin32:
+ skip("windows specific")
+ from _ffi import CDLL, types
+ wrong_kernel = CDLL('Kernel32.dll')
+ wrong_sleep = wrong_kernel.getfunc('Sleep', [types.uint], types.void)
+ try:
+ wrong_sleep(10)
+ except ValueError, e:
+ assert e.message.startswith('Procedure called with')
+ else:
+ assert 0, 'test must assert, wrong calling convention'
+
+ def test_func_fromaddr2(self):
+ if not self.iswin32:
+ skip("windows specific")
+ from _ffi import CDLL, types, FuncPtr
+ from _rawffi import FUNCFLAG_STDCALL
+ libm = CDLL(self.libm_name)
+ pow_addr = libm.getaddressindll('pow')
+ wrong_pow = FuncPtr.fromaddr(pow_addr, 'pow',
+ [types.double, types.double], types.double, FUNCFLAG_STDCALL)
+ try:
+ wrong_pow(2, 3) == 8
+ except ValueError, e:
+ assert e.message.startswith('Procedure called with')
+ else:
+ assert 0, 'test must assert, wrong calling convention'
+
+ def test_func_fromaddr3(self):
+ if not self.iswin32:
+ skip("windows specific")
+ from _ffi import WinDLL, types, FuncPtr
+ from _rawffi import FUNCFLAG_STDCALL
+ kernel = WinDLL('Kernel32.dll')
+ sleep_addr = kernel.getaddressindll('Sleep')
+ sleep = FuncPtr.fromaddr(sleep_addr, 'sleep', [types.uint],
+ types.void, FUNCFLAG_STDCALL)
+ sleep(10)
+
+
diff --git a/pypy/module/_ffi/test/test_type_converter.py b/pypy/module/_ffi/test/test_type_converter.py
--- a/pypy/module/_ffi/test/test_type_converter.py
+++ b/pypy/module/_ffi/test/test_type_converter.py
@@ -144,6 +144,7 @@
get_unichar_p = get_all
get_float = get_all
get_singlefloat = get_all
+ get_unsigned_which_fits_into_a_signed = get_all
def convert(self, w_ffitype, val):
self.val = val
diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py
@@ -1,11 +1,10 @@
-import py
import sys
from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
class Test__ffi(BaseTestPyPyC):
def test__ffi_call(self):
- from pypy.rlib.test.test_libffi import get_libm_name
+ from pypy.rlib.test.test_clibffi import get_libm_name
def main(libm_name):
try:
from _ffi import CDLL, types
@@ -42,7 +41,7 @@
def test__ffi_call_frame_does_not_escape(self):
- from pypy.rlib.test.test_libffi import get_libm_name
+ from pypy.rlib.test.test_clibffi import get_libm_name
def main(libm_name):
try:
from _ffi import CDLL, types
@@ -75,15 +74,22 @@
assert opnames.count('new_with_vtable') == 1
def test__ffi_call_releases_gil(self):
- from pypy.rlib.test.test_libffi import get_libc_name
+ from pypy.rlib.clibffi import get_libc_name
def main(libc_name, n):
import time
+ import os
from threading import Thread
- from _ffi import CDLL, types
#
- libc = CDLL(libc_name)
- sleep = libc.getfunc('sleep', [types.uint], types.uint)
- delays = [0]*n + [1]
+ if os.name == 'nt':
+ from _ffi import WinDLL, types
+ libc = WinDLL(libc_name)
+ sleep = libc.getfunc('Sleep', [types.uint], types.uint)
+ delays = [0]*n + [1000]
+ else:
+ from _ffi import CDLL, types
+ libc = CDLL(libc_name)
+ sleep = libc.getfunc('sleep', [types.uint], types.uint)
+ delays = [0]*n + [1]
#
def loop_of_sleeps(i, delays):
for delay in delays:
@@ -97,7 +103,6 @@
thread.join()
end = time.time()
return end - start
- #
log = self.run(main, [get_libc_name(), 200], threshold=150,
import_site=True)
assert 1 <= log.result <= 1.5 # at most 0.5 seconds of overhead
@@ -106,7 +111,7 @@
def test_ctypes_call(self):
- from pypy.rlib.test.test_libffi import get_libm_name
+ from pypy.rlib.test.test_clibffi import get_libm_name
def main(libm_name):
import ctypes
libm = ctypes.CDLL(libm_name)
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -1,15 +1,17 @@
from __future__ import with_statement
from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.rlib.objectmodel import specialize, enforceargs, we_are_translated
+from pypy.rlib.objectmodel import specialize, enforceargs
from pypy.rlib.rarithmetic import intmask, r_uint, r_singlefloat, r_longlong
from pypy.rlib import jit
from pypy.rlib import clibffi
-from pypy.rlib.clibffi import get_libc_name, FUNCFLAG_CDECL, AbstractFuncPtr, \
- push_arg_as_ffiptr, c_ffi_call, FFI_TYPE_STRUCT
+from pypy.rlib.clibffi import FUNCFLAG_CDECL, FUNCFLAG_STDCALL, \
+ AbstractFuncPtr, push_arg_as_ffiptr, c_ffi_call, FFI_TYPE_STRUCT
from pypy.rlib.rdynload import dlopen, dlclose, dlsym, dlsym_byordinal
from pypy.rlib.rdynload import DLLHANDLE
+import os
+
class types(object):
"""
This namespace contains the primitive types you can use to declare the
@@ -374,7 +376,7 @@
else:
res = None
self._free_buffers(ll_result, ll_args)
- #check_fficall_result(ffires, self.flags)
+ clibffi.check_fficall_result(ffires, self.flags)
return res
def _free_buffers(self, ll_result, ll_args):
@@ -416,6 +418,11 @@
def getaddressindll(self, name):
return dlsym(self.lib, name)
+if os.name == 'nt':
+ class WinDLL(CDLL):
+ def getpointer(self, name, argtypes, restype, flags=FUNCFLAG_STDCALL):
+ return Func(name, argtypes, restype, dlsym(self.lib, name),
+ flags=flags, keepalive=self)
# ======================================================================
@jit.oopspec('libffi_struct_getfield(ffitype, addr, offset)')
diff --git a/pypy/rlib/test/test_libffi.py b/pypy/rlib/test/test_libffi.py
--- a/pypy/rlib/test/test_libffi.py
+++ b/pypy/rlib/test/test_libffi.py
@@ -1,12 +1,13 @@
-import sys
+import os
import py
from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
-from pypy.rlib.test.test_clibffi import BaseFfiTest, get_libm_name, make_struct_ffitype_e
+from pypy.rlib.test.test_clibffi import BaseFfiTest, make_struct_ffitype_e
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED
-from pypy.rlib.libffi import (CDLL, Func, get_libc_name, ArgChain, types,
+from pypy.rpython.llinterp import LLException
+from pypy.rlib.libffi import (CDLL, ArgChain, types,
IS_32_BIT, array_getitem, array_setitem)
from pypy.rlib.libffi import (struct_getfield_int, struct_setfield_int,
struct_getfield_longlong, struct_setfield_longlong,
@@ -175,6 +176,15 @@
#
lltype.free(p, flavor='raw')
+ def test_windll(self):
+ if os.name != 'nt':
+ skip('Run only on windows')
+ from pypy.rlib.libffi import WinDLL
+ dll = WinDLL('Kernel32.dll')
+ sleep = dll.getpointer('Sleep',[types.uint], types.void)
+ chain = ArgChain()
+ chain.arg(10)
+ sleep.call(chain, lltype.Void, is_struct=False)
class TestLibffiCall(BaseFfiTest):
"""
@@ -219,9 +229,16 @@
eci = ExternalCompilationInfo(export_symbols=exports)
cls.libfoo_name = str(platform.compile([c_file], eci, 'x',
standalone=False))
+ cls.dll = cls.CDLL(cls.libfoo_name)
+
+ def teardown_class(cls):
+ if cls.dll:
+ cls.dll.__del__()
+ # Why doesn't this call cls.dll.__del__() ?
+ #del cls.dll
def get_libfoo(self):
- return self.CDLL(self.libfoo_name)
+ return self.dll
def call(self, funcspec, args, RESULT, is_struct=False, jitif=[]):
"""
@@ -536,4 +553,27 @@
assert p[1] == 34
lltype.free(p, flavor='raw')
lltype.free(ffi_point_struct, flavor='raw')
+
+ if os.name == 'nt':
+ def test_stdcall_simple(self):
+ """
+ int __stdcall std_diff_xy(int x, Signed y)
+ {
+ return x - y;
+ }
+ """
+ libfoo = self.get_libfoo()
+ func = (libfoo, 'std_diff_xy', [types.sint, types.signed], types.sint)
+ try:
+ self.call(func, [50, 8], lltype.Signed)
+ except ValueError, e:
+ assert e.message == 'Procedure called with not enough ' + \
+ 'arguments (8 bytes missing) or wrong calling convention'
+ except LLException, e:
+ #jitted code raises this
+ assert str(e) == "<LLException 'StackCheckError'>"
+ else:
+ assert 0, 'wrong calling convention should have raised'
+
+
More information about the pypy-commit
mailing list