mirror of
https://github.com/python/cpython.git
synced 2025-08-03 08:34:29 +00:00
Merge changes from the upstream version:
- cast is implemented as a foreign function now - On Windows, it is now possible to access functions exported by ordinal only
This commit is contained in:
parent
f4b066084a
commit
b03cb602e8
7 changed files with 191 additions and 92 deletions
|
@ -304,10 +304,11 @@ class CDLL(object):
|
|||
raise AttributeError, name
|
||||
return self.__getitem__(name)
|
||||
|
||||
def __getitem__(self, name):
|
||||
func = self._FuncPtr(name, self)
|
||||
func.__name__ = name
|
||||
setattr(self, name, func)
|
||||
def __getitem__(self, name_or_ordinal):
|
||||
func = self._FuncPtr((name_or_ordinal, self))
|
||||
if not isinstance(name_or_ordinal, (int, long)):
|
||||
func.__name__ = name_or_ordinal
|
||||
setattr(self, name_or_ordinal, func)
|
||||
return func
|
||||
|
||||
class PyDLL(CDLL):
|
||||
|
@ -384,21 +385,29 @@ if _os.name in ("nt", "ce"):
|
|||
|
||||
_pointer_type_cache[None] = c_void_p
|
||||
|
||||
# functions
|
||||
|
||||
from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, cast
|
||||
|
||||
if sizeof(c_uint) == sizeof(c_void_p):
|
||||
c_size_t = c_uint
|
||||
elif sizeof(c_ulong) == sizeof(c_void_p):
|
||||
c_size_t = c_ulong
|
||||
|
||||
# functions
|
||||
|
||||
from _ctypes import _memmove_addr, _memset_addr, _string_at_addr, _cast_addr
|
||||
|
||||
## void *memmove(void *, const void *, size_t);
|
||||
memmove = CFUNCTYPE(c_void_p, c_void_p, c_void_p, c_size_t)(_memmove_addr)
|
||||
|
||||
## void *memset(void *, int, size_t)
|
||||
memset = CFUNCTYPE(c_void_p, c_void_p, c_int, c_size_t)(_memset_addr)
|
||||
|
||||
def PYFUNCTYPE(restype, *argtypes):
|
||||
class CFunctionType(_CFuncPtr):
|
||||
_argtypes_ = argtypes
|
||||
_restype_ = restype
|
||||
_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
|
||||
return CFunctionType
|
||||
cast = PYFUNCTYPE(py_object, c_void_p, py_object)(_cast_addr)
|
||||
|
||||
_string_at = CFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
|
||||
def string_at(ptr, size=0):
|
||||
"""string_at(addr[, size]) -> string
|
||||
|
|
|
@ -2,6 +2,7 @@ import sys, unittest, struct, math
|
|||
from binascii import hexlify
|
||||
|
||||
from ctypes import *
|
||||
from ctypes.test import is_resource_enabled
|
||||
|
||||
def bin(s):
|
||||
return hexlify(buffer(s)).upper()
|
||||
|
@ -149,7 +150,7 @@ class Test(unittest.TestCase):
|
|||
self.failUnless(c_char.__ctype_le__ is c_char)
|
||||
self.failUnless(c_char.__ctype_be__ is c_char)
|
||||
|
||||
def test_struct_fields(self):
|
||||
def test_struct_fields_1(self):
|
||||
if sys.byteorder == "little":
|
||||
base = BigEndianStructure
|
||||
else:
|
||||
|
@ -198,17 +199,20 @@ class Test(unittest.TestCase):
|
|||
pass
|
||||
self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)])
|
||||
|
||||
# crashes on solaris with a core dump.
|
||||
def X_test_struct_fields(self):
|
||||
def test_struct_fields_2(self):
|
||||
# standard packing in struct uses no alignment.
|
||||
# So, we have to align using pad bytes.
|
||||
#
|
||||
# Unaligned accesses will crash Python (on those platforms that
|
||||
# don't allow it, like sparc solaris).
|
||||
if sys.byteorder == "little":
|
||||
base = BigEndianStructure
|
||||
fmt = ">bhid"
|
||||
fmt = ">bxhid"
|
||||
else:
|
||||
base = LittleEndianStructure
|
||||
fmt = "<bhid"
|
||||
fmt = "<bxhid"
|
||||
|
||||
class S(base):
|
||||
_pack_ = 1 # struct with '<' or '>' uses standard alignment.
|
||||
_fields_ = [("b", c_byte),
|
||||
("h", c_short),
|
||||
("i", c_int),
|
||||
|
@ -218,5 +222,54 @@ class Test(unittest.TestCase):
|
|||
s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
|
||||
self.failUnlessEqual(bin(s1), bin(s2))
|
||||
|
||||
if is_resource_enabled("unaligned_access"):
|
||||
|
||||
def test_unaligned_nonnative_struct_fields(self):
|
||||
if sys.byteorder == "little":
|
||||
base = BigEndianStructure
|
||||
fmt = ">b h xi xd"
|
||||
else:
|
||||
base = LittleEndianStructure
|
||||
fmt = "<b h xi xd"
|
||||
|
||||
class S(base):
|
||||
_pack_ = 1
|
||||
_fields_ = [("b", c_byte),
|
||||
|
||||
("h", c_short),
|
||||
|
||||
("_1", c_byte),
|
||||
("i", c_int),
|
||||
|
||||
("_2", c_byte),
|
||||
("d", c_double)]
|
||||
|
||||
s1 = S(0x12, 0x1234, 0, 0x12345678, 0, 3.14)
|
||||
s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
|
||||
self.failUnlessEqual(bin(s1), bin(s2))
|
||||
|
||||
def test_unaligned_native_struct_fields(self):
|
||||
if sys.byteorder == "little":
|
||||
fmt = "<b h xi xd"
|
||||
else:
|
||||
base = LittleEndianStructure
|
||||
fmt = ">b h xi xd"
|
||||
|
||||
class S(Structure):
|
||||
_pack_ = 1
|
||||
_fields_ = [("b", c_byte),
|
||||
|
||||
("h", c_short),
|
||||
|
||||
("_1", c_byte),
|
||||
("i", c_int),
|
||||
|
||||
("_2", c_byte),
|
||||
("d", c_double)]
|
||||
|
||||
s1 = S(0x12, 0x1234, 0, 0x12345678, 0, 3.14)
|
||||
s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
|
||||
self.failUnlessEqual(bin(s1), bin(s2))
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -179,7 +179,7 @@ else:
|
|||
def __getattr__(self, name):
|
||||
if name[:2] == '__' and name[-2:] == '__':
|
||||
raise AttributeError, name
|
||||
func = self._FuncPtr("s_" + name, self)
|
||||
func = self._FuncPtr(("s_" + name, self))
|
||||
setattr(self, name, func)
|
||||
return func
|
||||
|
||||
|
|
|
@ -17,8 +17,11 @@ class LoaderTest(unittest.TestCase):
|
|||
name = "libc.so"
|
||||
elif sys.platform == "sunos5":
|
||||
name = "libc.so"
|
||||
elif sys.platform.startswith("netbsd"):
|
||||
name = "libc.so"
|
||||
else:
|
||||
name = "libc.so.6"
|
||||
## print (sys.platform, os.name)
|
||||
cdll.load(name)
|
||||
self.assertRaises(OSError, cdll.load, self.unknowndll)
|
||||
|
||||
|
@ -37,5 +40,31 @@ class LoaderTest(unittest.TestCase):
|
|||
cdll.find(name)
|
||||
self.assertRaises(OSError, cdll.find, self.unknowndll)
|
||||
|
||||
def test_load_library(self):
|
||||
if os.name == "nt":
|
||||
windll.load_library("kernel32").GetModuleHandleW
|
||||
windll.LoadLibrary("kernel32").GetModuleHandleW
|
||||
WinDLL("kernel32").GetModuleHandleW
|
||||
elif os.name == "ce":
|
||||
windll.load_library("coredll").GetModuleHandleW
|
||||
windll.LoadLibrary("coredll").GetModuleHandleW
|
||||
WinDLL("coredll").GetModuleHandleW
|
||||
|
||||
def test_load_ordinal_functions(self):
|
||||
if os.name in ("nt", "ce"):
|
||||
import _ctypes_test
|
||||
dll = WinDLL(_ctypes_test.__file__)
|
||||
# We load the same function both via ordinal and name
|
||||
func_ord = dll[2]
|
||||
func_name = dll.GetString
|
||||
# addressof gets the address where the function pointer is stored
|
||||
a_ord = addressof(func_ord)
|
||||
a_name = addressof(func_name)
|
||||
f_ord_addr = c_void_p.from_address(a_ord).value
|
||||
f_name_addr = c_void_p.from_address(a_name).value
|
||||
self.failUnlessEqual(hex(f_ord_addr), hex(f_name_addr))
|
||||
|
||||
self.failUnlessRaises(AttributeError, dll.__getitem__, 1234)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -20,5 +20,8 @@ class SizesTestCase(unittest.TestCase):
|
|||
self.failUnlessEqual(8, sizeof(c_int64))
|
||||
self.failUnlessEqual(8, sizeof(c_uint64))
|
||||
|
||||
def test_size_t(self):
|
||||
self.failUnlessEqual(sizeof(c_void_p), sizeof(c_size_t))
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue