summaryrefslogtreecommitdiffstats
path: root/Lib/ctypes
diff options
context:
space:
mode:
authorThomas Heller <theller@ctypes.org>2006-03-17 15:52:58 (GMT)
committerThomas Heller <theller@ctypes.org>2006-03-17 15:52:58 (GMT)
commitb03cb602e800efea164c7455344de13dfea37b55 (patch)
treee1d4fbef168daefbc2f4ccea71bfd7d97f9f8459 /Lib/ctypes
parentf4b066084a14194586399452baf05e050d58122c (diff)
downloadcpython-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__.py25
-rw-r--r--Lib/ctypes/test/test_byteswap.py65
-rw-r--r--Lib/ctypes/test/test_cfuncs.py2
-rw-r--r--Lib/ctypes/test/test_loading.py29
-rw-r--r--Lib/ctypes/test/test_sizes.py3
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()