diff options
author | Thomas Heller <theller@ctypes.org> | 2006-03-17 15:52:58 (GMT) |
---|---|---|
committer | Thomas Heller <theller@ctypes.org> | 2006-03-17 15:52:58 (GMT) |
commit | b03cb602e800efea164c7455344de13dfea37b55 (patch) | |
tree | e1d4fbef168daefbc2f4ccea71bfd7d97f9f8459 /Lib/ctypes | |
parent | f4b066084a14194586399452baf05e050d58122c (diff) | |
download | cpython-b03cb602e800efea164c7455344de13dfea37b55.zip cpython-b03cb602e800efea164c7455344de13dfea37b55.tar.gz cpython-b03cb602e800efea164c7455344de13dfea37b55.tar.bz2 |
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
Diffstat (limited to 'Lib/ctypes')
-rw-r--r-- | Lib/ctypes/__init__.py | 25 | ||||
-rw-r--r-- | Lib/ctypes/test/test_byteswap.py | 65 | ||||
-rw-r--r-- | Lib/ctypes/test/test_cfuncs.py | 2 | ||||
-rw-r--r-- | Lib/ctypes/test/test_loading.py | 29 | ||||
-rw-r--r-- | Lib/ctypes/test/test_sizes.py | 3 |
5 files changed, 109 insertions, 15 deletions
diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index dd0f640..a005594 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -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 diff --git a/Lib/ctypes/test/test_byteswap.py b/Lib/ctypes/test/test_byteswap.py index 1b31f90..55a264c 100644 --- a/Lib/ctypes/test/test_byteswap.py +++ b/Lib/ctypes/test/test_byteswap.py @@ -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() diff --git a/Lib/ctypes/test/test_cfuncs.py b/Lib/ctypes/test/test_cfuncs.py index 7c2b28b..6e0798d 100644 --- a/Lib/ctypes/test/test_cfuncs.py +++ b/Lib/ctypes/test/test_cfuncs.py @@ -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 diff --git a/Lib/ctypes/test/test_loading.py b/Lib/ctypes/test/test_loading.py index 80564b8..5a76bb4 100644 --- a/Lib/ctypes/test/test_loading.py +++ b/Lib/ctypes/test/test_loading.py @@ -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() diff --git a/Lib/ctypes/test/test_sizes.py b/Lib/ctypes/test/test_sizes.py index 6fb9ca0..208c00e 100644 --- a/Lib/ctypes/test/test_sizes.py +++ b/Lib/ctypes/test/test_sizes.py @@ -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() |