mirror of
https://github.com/python/cpython.git
synced 2025-11-09 14:06:30 +00:00
Copy ctypes-0.9.9.4 Python modules from external into the trunk.
This commit is contained in:
parent
cf567c1b9c
commit
babddfca75
59 changed files with 5941 additions and 0 deletions
14
Lib/ctypes/.CTYPES_DEVEL
Normal file
14
Lib/ctypes/.CTYPES_DEVEL
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
# -*- python -*-
|
||||||
|
def install():
|
||||||
|
import sys, os
|
||||||
|
|
||||||
|
from distutils.util import get_platform
|
||||||
|
plat_specifier = ".%s-%s" % (get_platform(), sys.version[0:3])
|
||||||
|
build_dir = os.path.join("..", 'build', 'lib' + plat_specifier)
|
||||||
|
|
||||||
|
p = os.path.abspath(os.path.join(os.path.dirname(__file__), build_dir))
|
||||||
|
sys.path.insert(0, p)
|
||||||
|
del sys
|
||||||
|
|
||||||
|
install()
|
||||||
|
del install
|
||||||
4
Lib/ctypes/.cvsignore
Normal file
4
Lib/ctypes/.cvsignore
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
com
|
||||||
489
Lib/ctypes/__init__.py
Normal file
489
Lib/ctypes/__init__.py
Normal file
|
|
@ -0,0 +1,489 @@
|
||||||
|
"""create and manipulate C data types in Python"""
|
||||||
|
|
||||||
|
# special developer support to use ctypes from the CVS sandbox,
|
||||||
|
# without installing it
|
||||||
|
import os as _os, sys as _sys
|
||||||
|
from itertools import chain as _chain
|
||||||
|
|
||||||
|
_magicfile = _os.path.join(_os.path.dirname(__file__), ".CTYPES_DEVEL")
|
||||||
|
if _os.path.isfile(_magicfile):
|
||||||
|
execfile(_magicfile)
|
||||||
|
del _magicfile
|
||||||
|
|
||||||
|
__version__ = "0.9.9.4"
|
||||||
|
|
||||||
|
from _ctypes import Union, Structure, Array
|
||||||
|
from _ctypes import _Pointer
|
||||||
|
from _ctypes import CFuncPtr as _CFuncPtr
|
||||||
|
from _ctypes import __version__ as _ctypes_version
|
||||||
|
try:
|
||||||
|
from _ctypes import RTLD_LOCAL, RTLD_GLOBAL
|
||||||
|
except (ImportError, AttributeError):
|
||||||
|
RTLD_GLOBAL = RTLD_LOCAL = None
|
||||||
|
|
||||||
|
from _ctypes import ArgumentError
|
||||||
|
|
||||||
|
from struct import calcsize as _calcsize
|
||||||
|
|
||||||
|
if __version__ != _ctypes_version:
|
||||||
|
raise Exception, ("Version number mismatch", __version__, _ctypes_version)
|
||||||
|
|
||||||
|
if _os.name in ("nt", "ce"):
|
||||||
|
from _ctypes import FormatError
|
||||||
|
|
||||||
|
from _ctypes import FUNCFLAG_CDECL as _FUNCFLAG_CDECL, \
|
||||||
|
FUNCFLAG_PYTHONAPI as _FUNCFLAG_PYTHONAPI
|
||||||
|
|
||||||
|
from ctypes._loader import LibraryLoader
|
||||||
|
|
||||||
|
"""
|
||||||
|
WINOLEAPI -> HRESULT
|
||||||
|
WINOLEAPI_(type)
|
||||||
|
|
||||||
|
STDMETHODCALLTYPE
|
||||||
|
|
||||||
|
STDMETHOD(name)
|
||||||
|
STDMETHOD_(type, name)
|
||||||
|
|
||||||
|
STDAPICALLTYPE
|
||||||
|
"""
|
||||||
|
|
||||||
|
def create_string_buffer(init, size=None):
|
||||||
|
"""create_string_buffer(aString) -> character array
|
||||||
|
create_string_buffer(anInteger) -> character array
|
||||||
|
create_string_buffer(aString, anInteger) -> character array
|
||||||
|
"""
|
||||||
|
if isinstance(init, (str, unicode)):
|
||||||
|
if size is None:
|
||||||
|
size = len(init)+1
|
||||||
|
buftype = c_char * size
|
||||||
|
buf = buftype()
|
||||||
|
buf.value = init
|
||||||
|
return buf
|
||||||
|
elif isinstance(init, (int, long)):
|
||||||
|
buftype = c_char * init
|
||||||
|
buf = buftype()
|
||||||
|
return buf
|
||||||
|
raise TypeError, init
|
||||||
|
|
||||||
|
def c_buffer(init, size=None):
|
||||||
|
## "deprecated, use create_string_buffer instead"
|
||||||
|
## import warnings
|
||||||
|
## warnings.warn("c_buffer is deprecated, use create_string_buffer instead",
|
||||||
|
## DeprecationWarning, stacklevel=2)
|
||||||
|
return create_string_buffer(init, size)
|
||||||
|
|
||||||
|
_c_functype_cache = {}
|
||||||
|
def CFUNCTYPE(restype, *argtypes):
|
||||||
|
"""CFUNCTYPE(restype, *argtypes) -> function prototype.
|
||||||
|
|
||||||
|
restype: the result type
|
||||||
|
argtypes: a sequence specifying the argument types
|
||||||
|
|
||||||
|
The function prototype can be called in three ways to create a
|
||||||
|
callable object:
|
||||||
|
|
||||||
|
prototype(funct) - returns a C callable function calling funct
|
||||||
|
prototype(vtbl_index, method_name[, paramflags]) - a Python callable that calls a COM method
|
||||||
|
prototype(funct_name, dll[, paramflags]) - a Python callable that calls an exported function in a dll
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return _c_functype_cache[(restype, argtypes)]
|
||||||
|
except KeyError:
|
||||||
|
class CFunctionType(_CFuncPtr):
|
||||||
|
_argtypes_ = argtypes
|
||||||
|
_restype_ = restype
|
||||||
|
_flags_ = _FUNCFLAG_CDECL
|
||||||
|
_c_functype_cache[(restype, argtypes)] = CFunctionType
|
||||||
|
return CFunctionType
|
||||||
|
|
||||||
|
if _os.name in ("nt", "ce"):
|
||||||
|
from _ctypes import LoadLibrary as _dlopen
|
||||||
|
from _ctypes import FUNCFLAG_STDCALL as _FUNCFLAG_STDCALL
|
||||||
|
if _os.name == "ce":
|
||||||
|
# 'ce' doesn't have the stdcall calling convention
|
||||||
|
_FUNCFLAG_STDCALL = _FUNCFLAG_CDECL
|
||||||
|
|
||||||
|
_win_functype_cache = {}
|
||||||
|
def WINFUNCTYPE(restype, *argtypes):
|
||||||
|
# docstring set later (very similar to CFUNCTYPE.__doc__)
|
||||||
|
try:
|
||||||
|
return _win_functype_cache[(restype, argtypes)]
|
||||||
|
except KeyError:
|
||||||
|
class WinFunctionType(_CFuncPtr):
|
||||||
|
_argtypes_ = argtypes
|
||||||
|
_restype_ = restype
|
||||||
|
_flags_ = _FUNCFLAG_STDCALL
|
||||||
|
_win_functype_cache[(restype, argtypes)] = WinFunctionType
|
||||||
|
return WinFunctionType
|
||||||
|
if WINFUNCTYPE.__doc__:
|
||||||
|
WINFUNCTYPE.__doc__ = CFUNCTYPE.__doc__.replace("CFUNCTYPE", "WINFUNCTYPE")
|
||||||
|
|
||||||
|
elif _os.name == "posix":
|
||||||
|
from _ctypes import dlopen as _dlopen
|
||||||
|
|
||||||
|
from _ctypes import sizeof, byref, addressof, alignment
|
||||||
|
from _ctypes import _SimpleCData
|
||||||
|
|
||||||
|
class py_object(_SimpleCData):
|
||||||
|
_type_ = "O"
|
||||||
|
|
||||||
|
class c_short(_SimpleCData):
|
||||||
|
_type_ = "h"
|
||||||
|
|
||||||
|
class c_ushort(_SimpleCData):
|
||||||
|
_type_ = "H"
|
||||||
|
|
||||||
|
class c_long(_SimpleCData):
|
||||||
|
_type_ = "l"
|
||||||
|
|
||||||
|
class c_ulong(_SimpleCData):
|
||||||
|
_type_ = "L"
|
||||||
|
|
||||||
|
if _calcsize("i") == _calcsize("l"):
|
||||||
|
# if int and long have the same size, make c_int an alias for c_long
|
||||||
|
c_int = c_long
|
||||||
|
c_uint = c_ulong
|
||||||
|
else:
|
||||||
|
class c_int(_SimpleCData):
|
||||||
|
_type_ = "i"
|
||||||
|
|
||||||
|
class c_uint(_SimpleCData):
|
||||||
|
_type_ = "I"
|
||||||
|
|
||||||
|
class c_float(_SimpleCData):
|
||||||
|
_type_ = "f"
|
||||||
|
|
||||||
|
class c_double(_SimpleCData):
|
||||||
|
_type_ = "d"
|
||||||
|
|
||||||
|
if _calcsize("l") == _calcsize("q"):
|
||||||
|
# if long and long long have the same size, make c_longlong an alias for c_long
|
||||||
|
c_longlong = c_long
|
||||||
|
c_ulonglong = c_ulong
|
||||||
|
else:
|
||||||
|
class c_longlong(_SimpleCData):
|
||||||
|
_type_ = "q"
|
||||||
|
|
||||||
|
class c_ulonglong(_SimpleCData):
|
||||||
|
_type_ = "Q"
|
||||||
|
## def from_param(cls, val):
|
||||||
|
## return ('d', float(val), val)
|
||||||
|
## from_param = classmethod(from_param)
|
||||||
|
|
||||||
|
class c_ubyte(_SimpleCData):
|
||||||
|
_type_ = "B"
|
||||||
|
c_ubyte.__ctype_le__ = c_ubyte.__ctype_be__ = c_ubyte
|
||||||
|
# backward compatibility:
|
||||||
|
##c_uchar = c_ubyte
|
||||||
|
|
||||||
|
class c_byte(_SimpleCData):
|
||||||
|
_type_ = "b"
|
||||||
|
c_byte.__ctype_le__ = c_byte.__ctype_be__ = c_byte
|
||||||
|
|
||||||
|
class c_char(_SimpleCData):
|
||||||
|
_type_ = "c"
|
||||||
|
c_char.__ctype_le__ = c_char.__ctype_be__ = c_char
|
||||||
|
|
||||||
|
class c_char_p(_SimpleCData):
|
||||||
|
_type_ = "z"
|
||||||
|
|
||||||
|
class c_void_p(_SimpleCData):
|
||||||
|
_type_ = "P"
|
||||||
|
c_voidp = c_void_p # backwards compatibility (to a bug)
|
||||||
|
|
||||||
|
# This cache maps types to pointers to them.
|
||||||
|
_pointer_type_cache = {}
|
||||||
|
|
||||||
|
def POINTER(cls):
|
||||||
|
try:
|
||||||
|
return _pointer_type_cache[cls]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
if type(cls) is str:
|
||||||
|
klass = type(_Pointer)("LP_%s" % cls,
|
||||||
|
(_Pointer,),
|
||||||
|
{})
|
||||||
|
_pointer_type_cache[id(klass)] = klass
|
||||||
|
return klass
|
||||||
|
else:
|
||||||
|
name = "LP_%s" % cls.__name__
|
||||||
|
klass = type(_Pointer)(name,
|
||||||
|
(_Pointer,),
|
||||||
|
{'_type_': cls})
|
||||||
|
_pointer_type_cache[cls] = klass
|
||||||
|
return klass
|
||||||
|
|
||||||
|
try:
|
||||||
|
from _ctypes import set_conversion_mode
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if _os.name in ("nt", "ce"):
|
||||||
|
set_conversion_mode("mbcs", "ignore")
|
||||||
|
else:
|
||||||
|
set_conversion_mode("ascii", "strict")
|
||||||
|
|
||||||
|
class c_wchar_p(_SimpleCData):
|
||||||
|
_type_ = "Z"
|
||||||
|
|
||||||
|
class c_wchar(_SimpleCData):
|
||||||
|
_type_ = "u"
|
||||||
|
|
||||||
|
POINTER(c_wchar).from_param = c_wchar_p.from_param #_SimpleCData.c_wchar_p_from_param
|
||||||
|
|
||||||
|
def create_unicode_buffer(init, size=None):
|
||||||
|
"""create_unicode_buffer(aString) -> character array
|
||||||
|
create_unicode_buffer(anInteger) -> character array
|
||||||
|
create_unicode_buffer(aString, anInteger) -> character array
|
||||||
|
"""
|
||||||
|
if isinstance(init, (str, unicode)):
|
||||||
|
if size is None:
|
||||||
|
size = len(init)+1
|
||||||
|
buftype = c_wchar * size
|
||||||
|
buf = buftype()
|
||||||
|
buf.value = init
|
||||||
|
return buf
|
||||||
|
elif isinstance(init, (int, long)):
|
||||||
|
buftype = c_wchar * init
|
||||||
|
buf = buftype()
|
||||||
|
return buf
|
||||||
|
raise TypeError, init
|
||||||
|
|
||||||
|
POINTER(c_char).from_param = c_char_p.from_param #_SimpleCData.c_char_p_from_param
|
||||||
|
|
||||||
|
# XXX Deprecated
|
||||||
|
def SetPointerType(pointer, cls):
|
||||||
|
if _pointer_type_cache.get(cls, None) is not None:
|
||||||
|
raise RuntimeError, \
|
||||||
|
"This type already exists in the cache"
|
||||||
|
if not _pointer_type_cache.has_key(id(pointer)):
|
||||||
|
raise RuntimeError, \
|
||||||
|
"What's this???"
|
||||||
|
pointer.set_type(cls)
|
||||||
|
_pointer_type_cache[cls] = pointer
|
||||||
|
del _pointer_type_cache[id(pointer)]
|
||||||
|
|
||||||
|
|
||||||
|
def pointer(inst):
|
||||||
|
return POINTER(type(inst))(inst)
|
||||||
|
|
||||||
|
# XXX Deprecated
|
||||||
|
def ARRAY(typ, len):
|
||||||
|
return typ * len
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
|
||||||
|
class CDLL(object):
|
||||||
|
"""An instance of this class represents a loaded dll/shared
|
||||||
|
library, exporting functions using the standard C calling
|
||||||
|
convention (named 'cdecl' on Windows).
|
||||||
|
|
||||||
|
The exported functions can be accessed as attributes, or by
|
||||||
|
indexing with the function name. Examples:
|
||||||
|
|
||||||
|
<obj>.qsort -> callable object
|
||||||
|
<obj>['qsort'] -> callable object
|
||||||
|
|
||||||
|
Calling the functions releases the Python GIL during the call and
|
||||||
|
reaquires it afterwards.
|
||||||
|
"""
|
||||||
|
class _FuncPtr(_CFuncPtr):
|
||||||
|
_flags_ = _FUNCFLAG_CDECL
|
||||||
|
_restype_ = c_int # default, can be overridden in instances
|
||||||
|
|
||||||
|
def __init__(self, name, mode=RTLD_LOCAL, handle=None):
|
||||||
|
self._name = name
|
||||||
|
if handle is None:
|
||||||
|
self._handle = _dlopen(self._name, mode)
|
||||||
|
else:
|
||||||
|
self._handle = handle
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<%s '%s', handle %x at %x>" % \
|
||||||
|
(self.__class__.__name__, self._name,
|
||||||
|
(self._handle & (_sys.maxint*2 + 1)),
|
||||||
|
id(self))
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
if name.startswith('__') and name.endswith('__'):
|
||||||
|
raise AttributeError, name
|
||||||
|
return self.__getitem__(name)
|
||||||
|
|
||||||
|
def __getitem__(self, name):
|
||||||
|
func = self._FuncPtr(name, self)
|
||||||
|
func.__name__ = name
|
||||||
|
setattr(self, name, func)
|
||||||
|
return func
|
||||||
|
|
||||||
|
class PyDLL(CDLL):
|
||||||
|
"""This class represents the Python library itself. It allows to
|
||||||
|
access Python API functions. The GIL is not released, and
|
||||||
|
Python exceptions are handled correctly.
|
||||||
|
"""
|
||||||
|
class _FuncPtr(_CFuncPtr):
|
||||||
|
_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
|
||||||
|
_restype_ = c_int # default, can be overridden in instances
|
||||||
|
|
||||||
|
if _os.name in ("nt", "ce"):
|
||||||
|
|
||||||
|
class WinDLL(CDLL):
|
||||||
|
"""This class represents a dll exporting functions using the
|
||||||
|
Windows stdcall calling convention.
|
||||||
|
"""
|
||||||
|
class _FuncPtr(_CFuncPtr):
|
||||||
|
_flags_ = _FUNCFLAG_STDCALL
|
||||||
|
_restype_ = c_int # default, can be overridden in instances
|
||||||
|
|
||||||
|
# XXX Hm, what about HRESULT as normal parameter?
|
||||||
|
# Mustn't it derive from c_long then?
|
||||||
|
from _ctypes import _check_HRESULT, _SimpleCData
|
||||||
|
class HRESULT(_SimpleCData):
|
||||||
|
_type_ = "l"
|
||||||
|
# _check_retval_ is called with the function's result when it
|
||||||
|
# is used as restype. It checks for the FAILED bit, and
|
||||||
|
# raises a WindowsError if it is set.
|
||||||
|
#
|
||||||
|
# The _check_retval_ method is implemented in C, so that the
|
||||||
|
# method definition itself is not included in the traceback
|
||||||
|
# when it raises an error - that is what we want (and Python
|
||||||
|
# doesn't have a way to raise an exception in the caller's
|
||||||
|
# frame).
|
||||||
|
_check_retval_ = _check_HRESULT
|
||||||
|
|
||||||
|
class OleDLL(CDLL):
|
||||||
|
"""This class represents a dll exporting functions using the
|
||||||
|
Windows stdcall calling convention, and returning HRESULT.
|
||||||
|
HRESULT error values are automatically raised as WindowsError
|
||||||
|
exceptions.
|
||||||
|
"""
|
||||||
|
class _FuncPtr(_CFuncPtr):
|
||||||
|
_flags_ = _FUNCFLAG_STDCALL
|
||||||
|
_restype_ = HRESULT
|
||||||
|
|
||||||
|
cdll = LibraryLoader(CDLL)
|
||||||
|
pydll = LibraryLoader(PyDLL)
|
||||||
|
|
||||||
|
if _os.name in ("nt", "ce"):
|
||||||
|
pythonapi = PyDLL("python dll", None, _sys.dllhandle)
|
||||||
|
elif _sys.platform == "cygwin":
|
||||||
|
pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
|
||||||
|
else:
|
||||||
|
pythonapi = PyDLL(None)
|
||||||
|
|
||||||
|
|
||||||
|
if _os.name in ("nt", "ce"):
|
||||||
|
windll = LibraryLoader(WinDLL)
|
||||||
|
oledll = LibraryLoader(OleDLL)
|
||||||
|
|
||||||
|
if _os.name == "nt":
|
||||||
|
GetLastError = windll.kernel32.GetLastError
|
||||||
|
else:
|
||||||
|
GetLastError = windll.coredll.GetLastError
|
||||||
|
|
||||||
|
def WinError(code=None, descr=None):
|
||||||
|
if code is None:
|
||||||
|
code = GetLastError()
|
||||||
|
if descr is None:
|
||||||
|
descr = FormatError(code).strip()
|
||||||
|
return WindowsError(code, descr)
|
||||||
|
|
||||||
|
_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
|
||||||
|
|
||||||
|
## 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)
|
||||||
|
|
||||||
|
_string_at = CFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
|
||||||
|
def string_at(ptr, size=0):
|
||||||
|
"""string_at(addr[, size]) -> string
|
||||||
|
|
||||||
|
Return the string at addr."""
|
||||||
|
return _string_at(ptr, size)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from _ctypes import _wstring_at_addr
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
_wstring_at = CFUNCTYPE(py_object, c_void_p, c_int)(_wstring_at_addr)
|
||||||
|
def wstring_at(ptr, size=0):
|
||||||
|
"""wstring_at(addr[, size]) -> string
|
||||||
|
|
||||||
|
Return the string at addr."""
|
||||||
|
return _wstring_at(ptr, size)
|
||||||
|
|
||||||
|
|
||||||
|
if _os.name == "nt": # COM stuff
|
||||||
|
def DllGetClassObject(rclsid, riid, ppv):
|
||||||
|
# First ask ctypes.com.server than comtypes.server for the
|
||||||
|
# class object.
|
||||||
|
|
||||||
|
# trick py2exe by doing dynamic imports
|
||||||
|
result = -2147221231 # CLASS_E_CLASSNOTAVAILABLE
|
||||||
|
try:
|
||||||
|
ctcom = __import__("ctypes.com.server", globals(), locals(), ['*'])
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
result = ctcom.DllGetClassObject(rclsid, riid, ppv)
|
||||||
|
|
||||||
|
if result == -2147221231: # CLASS_E_CLASSNOTAVAILABLE
|
||||||
|
try:
|
||||||
|
ccom = __import__("comtypes.server", globals(), locals(), ['*'])
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
result = ccom.DllGetClassObject(rclsid, riid, ppv)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def DllCanUnloadNow():
|
||||||
|
# First ask ctypes.com.server than comtypes.server if we can unload or not.
|
||||||
|
# trick py2exe by doing dynamic imports
|
||||||
|
result = 0 # S_OK
|
||||||
|
try:
|
||||||
|
ctcom = __import__("ctypes.com.server", globals(), locals(), ['*'])
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
result = ctcom.DllCanUnloadNow()
|
||||||
|
if result != 0: # != S_OK
|
||||||
|
return result
|
||||||
|
|
||||||
|
try:
|
||||||
|
ccom = __import__("comtypes.server", globals(), locals(), ['*'])
|
||||||
|
except ImportError:
|
||||||
|
return result
|
||||||
|
try:
|
||||||
|
return ccom.DllCanUnloadNow()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
return result
|
||||||
|
|
||||||
|
from ctypes._endian import BigEndianStructure, LittleEndianStructure
|
||||||
|
|
||||||
|
# Fill in specifically-sized types
|
||||||
|
c_int8 = c_byte
|
||||||
|
c_uint8 = c_ubyte
|
||||||
|
for kind in [c_short, c_int, c_long, c_longlong]:
|
||||||
|
if sizeof(kind) == 2: c_int16 = kind
|
||||||
|
elif sizeof(kind) == 4: c_int32 = kind
|
||||||
|
elif sizeof(kind) == 8: c_int64 = kind
|
||||||
|
for kind in [c_ushort, c_uint, c_ulong, c_ulonglong]:
|
||||||
|
if sizeof(kind) == 2: c_uint16 = kind
|
||||||
|
elif sizeof(kind) == 4: c_uint32 = kind
|
||||||
|
elif sizeof(kind) == 8: c_uint64 = kind
|
||||||
|
del(kind)
|
||||||
58
Lib/ctypes/_endian.py
Normal file
58
Lib/ctypes/_endian.py
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
import sys
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
_array_type = type(c_int * 3)
|
||||||
|
|
||||||
|
def _other_endian(typ):
|
||||||
|
"""Return the type with the 'other' byte order. Simple types like
|
||||||
|
c_int and so on already have __ctype_be__ and __ctype_le__
|
||||||
|
attributes which contain the types, for more complicated types
|
||||||
|
only arrays are supported.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return getattr(typ, _OTHER_ENDIAN)
|
||||||
|
except AttributeError:
|
||||||
|
if type(typ) == _array_type:
|
||||||
|
return _other_endian(typ._type_) * typ._length_
|
||||||
|
raise TypeError("This type does not support other endian: %s" % typ)
|
||||||
|
|
||||||
|
class _swapped_meta(type(Structure)):
|
||||||
|
def __setattr__(self, attrname, value):
|
||||||
|
if attrname == "_fields_":
|
||||||
|
fields = []
|
||||||
|
for desc in value:
|
||||||
|
name = desc[0]
|
||||||
|
typ = desc[1]
|
||||||
|
rest = desc[2:]
|
||||||
|
fields.append((name, _other_endian(typ)) + rest)
|
||||||
|
value = fields
|
||||||
|
super(_swapped_meta, self).__setattr__(attrname, value)
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
# Note: The Structure metaclass checks for the *presence* (not the
|
||||||
|
# value!) of a _swapped_bytes_ attribute to determine the bit order in
|
||||||
|
# structures containing bit fields.
|
||||||
|
|
||||||
|
if sys.byteorder == "little":
|
||||||
|
_OTHER_ENDIAN = "__ctype_be__"
|
||||||
|
|
||||||
|
LittleEndianStructure = Structure
|
||||||
|
|
||||||
|
class BigEndianStructure(Structure):
|
||||||
|
"""Structure with big endian byte order"""
|
||||||
|
__metaclass__ = _swapped_meta
|
||||||
|
_swappedbytes_ = None
|
||||||
|
|
||||||
|
elif sys.byteorder == "big":
|
||||||
|
_OTHER_ENDIAN = "__ctype_le__"
|
||||||
|
|
||||||
|
BigEndianStructure = Structure
|
||||||
|
class LittleEndianStructure(Structure):
|
||||||
|
"""Structure with little endian byte order"""
|
||||||
|
__metaclass__ = _swapped_meta
|
||||||
|
_swappedbytes_ = None
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Invalid byteorder")
|
||||||
|
|
||||||
262
Lib/ctypes/_loader.py
Normal file
262
Lib/ctypes/_loader.py
Normal file
|
|
@ -0,0 +1,262 @@
|
||||||
|
# WORK IN PROGRESS! DO NOT (yet) USE!
|
||||||
|
import sys, os
|
||||||
|
import ctypes
|
||||||
|
|
||||||
|
__all__ = ["LibraryLoader", "RTLD_LOCAL", "RTLD_GLOBAL"]
|
||||||
|
|
||||||
|
if os.name in ("nt", "ce"):
|
||||||
|
from _ctypes import LoadLibrary as dlopen
|
||||||
|
RTLD_LOCAL = RTLD_GLOBAL = None
|
||||||
|
else:
|
||||||
|
from _ctypes import dlopen, RTLD_LOCAL, RTLD_GLOBAL
|
||||||
|
|
||||||
|
# _findLib(name) returns an iterable of possible names for a library.
|
||||||
|
if os.name in ("nt", "ce"):
|
||||||
|
def _findLib(name):
|
||||||
|
return [name]
|
||||||
|
|
||||||
|
if os.name == "posix" and sys.platform == "darwin":
|
||||||
|
from ctypes.macholib.dyld import dyld_find as _dyld_find
|
||||||
|
def _findLib(name):
|
||||||
|
possible = ['lib%s.dylib' % name,
|
||||||
|
'%s.dylib' % name,
|
||||||
|
'%s.framework/%s' % (name, name)]
|
||||||
|
for name in possible:
|
||||||
|
try:
|
||||||
|
return [_dyld_find(name)]
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
return []
|
||||||
|
|
||||||
|
elif os.name == "posix":
|
||||||
|
# Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
|
||||||
|
import re, tempfile
|
||||||
|
|
||||||
|
def _findLib_gcc(name):
|
||||||
|
expr = '[^\(\)\s]*lib%s\.[^\(\)\s]*' % name
|
||||||
|
cmd = 'if type gcc &>/dev/null; then CC=gcc; else CC=cc; fi;' \
|
||||||
|
'$CC -Wl,-t -o /dev/null 2>&1 -l' + name
|
||||||
|
try:
|
||||||
|
fdout, outfile = tempfile.mkstemp()
|
||||||
|
fd = os.popen(cmd)
|
||||||
|
trace = fd.read()
|
||||||
|
err = fd.close()
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
os.unlink(outfile)
|
||||||
|
except OSError, e:
|
||||||
|
if e.errno != errno.ENOENT:
|
||||||
|
raise
|
||||||
|
res = re.search(expr, trace)
|
||||||
|
if not res:
|
||||||
|
return None
|
||||||
|
return res.group(0)
|
||||||
|
|
||||||
|
def _findLib_ld(name):
|
||||||
|
expr = '/[^\(\)\s]*lib%s\.[^\(\)\s]*' % name
|
||||||
|
res = re.search(expr, os.popen('/sbin/ldconfig -p 2>/dev/null').read())
|
||||||
|
if not res:
|
||||||
|
return None
|
||||||
|
return res.group(0)
|
||||||
|
|
||||||
|
def _get_soname(f):
|
||||||
|
cmd = "objdump -p -j .dynamic 2>/dev/null " + f
|
||||||
|
res = re.search(r'\sSONAME\s+([^\s]+)', os.popen(cmd).read())
|
||||||
|
if not res:
|
||||||
|
return f
|
||||||
|
return res.group(1)
|
||||||
|
|
||||||
|
def _findLib(name):
|
||||||
|
lib = _findLib_ld(name)
|
||||||
|
if not lib:
|
||||||
|
lib = _findLib_gcc(name)
|
||||||
|
if not lib:
|
||||||
|
return [name]
|
||||||
|
return [_get_soname(lib)]
|
||||||
|
|
||||||
|
class LibraryLoader(object):
|
||||||
|
"""Loader for shared libraries.
|
||||||
|
|
||||||
|
Shared libraries are accessed when compiling/linking a program,
|
||||||
|
and when the program is run. The purpose of the 'find' method is
|
||||||
|
to locate a library similar to what the compiler does (on machines
|
||||||
|
with several versions of a shared library the most recent should
|
||||||
|
be loaded), while 'load' acts like when the program is run, and
|
||||||
|
uses the runtime loader directly. 'load_version' works like
|
||||||
|
'load' but tries to be platform independend (for cases where this
|
||||||
|
makes sense). Loading via attribute access is a shorthand
|
||||||
|
notation especially useful for interactive use."""
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, dlltype, mode=RTLD_LOCAL):
|
||||||
|
"""Create a library loader instance which loads libraries by
|
||||||
|
creating an instance of 'dlltype'. 'mode' can be RTLD_LOCAL
|
||||||
|
or RTLD_GLOBAL, it is ignored on Windows.
|
||||||
|
"""
|
||||||
|
self._dlltype = dlltype
|
||||||
|
self._mode = mode
|
||||||
|
|
||||||
|
def load(self, libname, mode=None):
|
||||||
|
"""Load and return the library with the given libname. On
|
||||||
|
most systems 'libname' is the filename of the shared library;
|
||||||
|
when it's not a pathname it will be searched in a system
|
||||||
|
dependend list of locations (on many systems additional search
|
||||||
|
paths can be specified by an environment variable). Sometimes
|
||||||
|
the extension (like '.dll' on Windows) can be omitted.
|
||||||
|
|
||||||
|
'mode' allows to override the default flags specified in the
|
||||||
|
constructor, it is ignored on Windows.
|
||||||
|
"""
|
||||||
|
if mode is None:
|
||||||
|
mode = self._mode
|
||||||
|
return self._load(libname, mode)
|
||||||
|
|
||||||
|
def load_library(self, libname, mode=None):
|
||||||
|
"""Load and return the library with the given libname. This
|
||||||
|
method passes the specified 'libname' directly to the
|
||||||
|
platform's library loading function (dlopen, or LoadLibrary).
|
||||||
|
|
||||||
|
'mode' allows to override the default flags specified in the
|
||||||
|
constructor, it is ignored on Windows.
|
||||||
|
"""
|
||||||
|
if mode is None:
|
||||||
|
mode = self._mode
|
||||||
|
return self._dlltype(libname, mode)
|
||||||
|
|
||||||
|
# alias name for backwards compatiblity
|
||||||
|
LoadLibrary = load_library
|
||||||
|
|
||||||
|
# Helpers for load and load_version - assembles a filename from name and filename
|
||||||
|
if os.name in ("nt", "ce"):
|
||||||
|
# Windows (XXX what about cygwin?)
|
||||||
|
def _plat_load_version(self, name, version, mode):
|
||||||
|
# not sure if this makes sense
|
||||||
|
if version is not None:
|
||||||
|
return self.load(name + version, mode)
|
||||||
|
return self.load(name, mode)
|
||||||
|
|
||||||
|
_load = load_library
|
||||||
|
|
||||||
|
elif os.name == "posix" and sys.platform == "darwin":
|
||||||
|
# Mac OS X
|
||||||
|
def _plat_load_version(self, name, version, mode):
|
||||||
|
if version:
|
||||||
|
return self.load("lib%s.%s.dylib" % (name, version), mode)
|
||||||
|
return self.load("lib%s.dylib" % name, mode)
|
||||||
|
|
||||||
|
def _load(self, libname, mode):
|
||||||
|
# _dyld_find raises ValueError, convert this into OSError
|
||||||
|
try:
|
||||||
|
pathname = _dyld_find(libname)
|
||||||
|
except ValueError:
|
||||||
|
raise OSError("Library %s could not be found" % libname)
|
||||||
|
return self.load_library(pathname, mode)
|
||||||
|
|
||||||
|
elif os.name == "posix":
|
||||||
|
# Posix
|
||||||
|
def _plat_load_version(self, name, version, mode):
|
||||||
|
if version:
|
||||||
|
return self.load("lib%s.so.%s" % (name, version), mode)
|
||||||
|
return self.load("lib%s.so" % name, mode)
|
||||||
|
|
||||||
|
_load = load_library
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Others, TBD
|
||||||
|
def _plat_load_version(self, name, version, mode=None):
|
||||||
|
return self.load(name, mode)
|
||||||
|
|
||||||
|
_load = load_library
|
||||||
|
|
||||||
|
def load_version(self, name, version=None, mode=None):
|
||||||
|
"""Build a (system dependend) filename from 'name' and
|
||||||
|
'version', then load and return it. 'name' is the library
|
||||||
|
name without any prefix like 'lib' and suffix like '.so' or
|
||||||
|
'.dylib'. This method should be used if a library is
|
||||||
|
available on different platforms, using the particular naming
|
||||||
|
convention of each platform.
|
||||||
|
|
||||||
|
'mode' allows to override the default flags specified in the
|
||||||
|
constructor, it is ignored on Windows.
|
||||||
|
"""
|
||||||
|
return self._plat_load_version(name, version, mode)
|
||||||
|
|
||||||
|
def find(self, name, mode=None):
|
||||||
|
"""Try to find a library, load and return it. 'name' is the
|
||||||
|
library name without any prefix like 'lib', suffix like '.so',
|
||||||
|
'.dylib' or version number (this is the form used for the
|
||||||
|
posix linker option '-l').
|
||||||
|
|
||||||
|
'mode' allows to override the default flags specified in the
|
||||||
|
constructor, it is ignored on Windows.
|
||||||
|
|
||||||
|
On windows, this method does the same as the 'load' method.
|
||||||
|
|
||||||
|
On other platforms, this function might call other programs
|
||||||
|
like the compiler to find the library. When using ctypes to
|
||||||
|
write a shared library wrapping, consider using .load() or
|
||||||
|
.load_version() instead.
|
||||||
|
"""
|
||||||
|
for libname in _findLib(name):
|
||||||
|
try:
|
||||||
|
return self.load(libname, mode)
|
||||||
|
except OSError:
|
||||||
|
continue
|
||||||
|
raise OSError("Library %r not found" % name)
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
"""Load a library via attribute access. Calls
|
||||||
|
.load_version(). The result is cached."""
|
||||||
|
if name.startswith("_"):
|
||||||
|
raise AttributeError(name)
|
||||||
|
dll = self.load_version(name)
|
||||||
|
setattr(self, name, dll)
|
||||||
|
return dll
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
# test code
|
||||||
|
|
||||||
|
class CDLL(object):
|
||||||
|
def __init__(self, name, mode):
|
||||||
|
self._handle = dlopen(name, mode)
|
||||||
|
self._name = name
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<%s '%s', handle %x at %x>" % \
|
||||||
|
(self.__class__.__name__, self._name,
|
||||||
|
(self._handle & (sys.maxint*2 + 1)),
|
||||||
|
id(self))
|
||||||
|
|
||||||
|
cdll = LibraryLoader(CDLL)
|
||||||
|
|
||||||
|
def test():
|
||||||
|
if os.name == "nt":
|
||||||
|
print cdll.msvcrt
|
||||||
|
print cdll.load("msvcrt")
|
||||||
|
# load_version looks more like an artefact:
|
||||||
|
print cdll.load_version("msvcr", "t")
|
||||||
|
print cdll.find("msvcrt")
|
||||||
|
|
||||||
|
if os.name == "posix":
|
||||||
|
# find and load_version
|
||||||
|
print cdll.find("m")
|
||||||
|
print cdll.find("c")
|
||||||
|
print cdll.load_version("crypto", "0.9.7")
|
||||||
|
|
||||||
|
# getattr
|
||||||
|
print cdll.m
|
||||||
|
print cdll.bz2
|
||||||
|
|
||||||
|
# load
|
||||||
|
if sys.platform == "darwin":
|
||||||
|
print cdll.load("libm.dylib")
|
||||||
|
print cdll.load("libcrypto.dylib")
|
||||||
|
print cdll.load("libSystem.dylib")
|
||||||
|
print cdll.load("System.framework/System")
|
||||||
|
else:
|
||||||
|
print cdll.load("libm.so")
|
||||||
|
print cdll.load("libcrypt.so")
|
||||||
|
print cdll.find("crypt")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test()
|
||||||
3
Lib/ctypes/macholib/.cvsignore
Normal file
3
Lib/ctypes/macholib/.cvsignore
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
.svn
|
||||||
7
Lib/ctypes/macholib/README.ctypes
Normal file
7
Lib/ctypes/macholib/README.ctypes
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
Files in this directory from from Bob Ippolito's py2app.
|
||||||
|
|
||||||
|
License: Any components of the py2app suite may be distributed under
|
||||||
|
the MIT or PSF open source licenses.
|
||||||
|
|
||||||
|
This is version 1.0, SVN revision 789, from 2006/01/25.
|
||||||
|
The main repository is http://svn.red-bean.com/bob/macholib/trunk/macholib/
|
||||||
9
Lib/ctypes/macholib/__init__.py
Normal file
9
Lib/ctypes/macholib/__init__.py
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
"""
|
||||||
|
Enough Mach-O to make your head spin.
|
||||||
|
|
||||||
|
See the relevant header files in /usr/include/mach-o
|
||||||
|
|
||||||
|
And also Apple's documentation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__version__ = '1.0'
|
||||||
166
Lib/ctypes/macholib/dyld.py
Normal file
166
Lib/ctypes/macholib/dyld.py
Normal file
|
|
@ -0,0 +1,166 @@
|
||||||
|
"""
|
||||||
|
dyld emulation
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from framework import framework_info
|
||||||
|
from dylib import dylib_info
|
||||||
|
from itertools import *
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'dyld_find', 'framework_find',
|
||||||
|
'framework_info', 'dylib_info',
|
||||||
|
]
|
||||||
|
|
||||||
|
# These are the defaults as per man dyld(1)
|
||||||
|
#
|
||||||
|
DEFAULT_FRAMEWORK_FALLBACK = [
|
||||||
|
os.path.expanduser("~/Library/Frameworks"),
|
||||||
|
"/Library/Frameworks",
|
||||||
|
"/Network/Library/Frameworks",
|
||||||
|
"/System/Library/Frameworks",
|
||||||
|
]
|
||||||
|
|
||||||
|
DEFAULT_LIBRARY_FALLBACK = [
|
||||||
|
os.path.expanduser("~/lib"),
|
||||||
|
"/usr/local/lib",
|
||||||
|
"/lib",
|
||||||
|
"/usr/lib",
|
||||||
|
]
|
||||||
|
|
||||||
|
def ensure_utf8(s):
|
||||||
|
"""Not all of PyObjC and Python understand unicode paths very well yet"""
|
||||||
|
if isinstance(s, unicode):
|
||||||
|
return s.encode('utf8')
|
||||||
|
return s
|
||||||
|
|
||||||
|
def dyld_env(env, var):
|
||||||
|
if env is None:
|
||||||
|
env = os.environ
|
||||||
|
rval = env.get(var)
|
||||||
|
if rval is None:
|
||||||
|
return []
|
||||||
|
return rval.split(':')
|
||||||
|
|
||||||
|
def dyld_image_suffix(env=None):
|
||||||
|
if env is None:
|
||||||
|
env = os.environ
|
||||||
|
return env.get('DYLD_IMAGE_SUFFIX')
|
||||||
|
|
||||||
|
def dyld_framework_path(env=None):
|
||||||
|
return dyld_env(env, 'DYLD_FRAMEWORK_PATH')
|
||||||
|
|
||||||
|
def dyld_library_path(env=None):
|
||||||
|
return dyld_env(env, 'DYLD_LIBRARY_PATH')
|
||||||
|
|
||||||
|
def dyld_fallback_framework_path(env=None):
|
||||||
|
return dyld_env(env, 'DYLD_FALLBACK_FRAMEWORK_PATH')
|
||||||
|
|
||||||
|
def dyld_fallback_library_path(env=None):
|
||||||
|
return dyld_env(env, 'DYLD_FALLBACK_LIBRARY_PATH')
|
||||||
|
|
||||||
|
def dyld_image_suffix_search(iterator, env=None):
|
||||||
|
"""For a potential path iterator, add DYLD_IMAGE_SUFFIX semantics"""
|
||||||
|
suffix = dyld_image_suffix(env)
|
||||||
|
if suffix is None:
|
||||||
|
return iterator
|
||||||
|
def _inject(iterator=iterator, suffix=suffix):
|
||||||
|
for path in iterator:
|
||||||
|
if path.endswith('.dylib'):
|
||||||
|
yield path[:-len('.dylib')] + suffix + '.dylib'
|
||||||
|
else:
|
||||||
|
yield path + suffix
|
||||||
|
yield path
|
||||||
|
return _inject()
|
||||||
|
|
||||||
|
def dyld_override_search(name, env=None):
|
||||||
|
# If DYLD_FRAMEWORK_PATH is set and this dylib_name is a
|
||||||
|
# framework name, use the first file that exists in the framework
|
||||||
|
# path if any. If there is none go on to search the DYLD_LIBRARY_PATH
|
||||||
|
# if any.
|
||||||
|
|
||||||
|
framework = framework_info(name)
|
||||||
|
|
||||||
|
if framework is not None:
|
||||||
|
for path in dyld_framework_path(env):
|
||||||
|
yield os.path.join(path, framework['name'])
|
||||||
|
|
||||||
|
# If DYLD_LIBRARY_PATH is set then use the first file that exists
|
||||||
|
# in the path. If none use the original name.
|
||||||
|
for path in dyld_library_path(env):
|
||||||
|
yield os.path.join(path, os.path.basename(name))
|
||||||
|
|
||||||
|
def dyld_executable_path_search(name, executable_path=None):
|
||||||
|
# If we haven't done any searching and found a library and the
|
||||||
|
# dylib_name starts with "@executable_path/" then construct the
|
||||||
|
# library name.
|
||||||
|
if name.startswith('@executable_path/') and executable_path is not None:
|
||||||
|
yield os.path.join(executable_path, name[len('@executable_path/'):])
|
||||||
|
|
||||||
|
def dyld_default_search(name, env=None):
|
||||||
|
yield name
|
||||||
|
|
||||||
|
framework = framework_info(name)
|
||||||
|
|
||||||
|
if framework is not None:
|
||||||
|
fallback_framework_path = dyld_fallback_framework_path(env)
|
||||||
|
for path in fallback_framework_path:
|
||||||
|
yield os.path.join(path, framework['name'])
|
||||||
|
|
||||||
|
fallback_library_path = dyld_fallback_library_path(env)
|
||||||
|
for path in fallback_library_path:
|
||||||
|
yield os.path.join(path, os.path.basename(name))
|
||||||
|
|
||||||
|
if framework is not None and not fallback_framework_path:
|
||||||
|
for path in DEFAULT_FRAMEWORK_FALLBACK:
|
||||||
|
yield os.path.join(path, framework['name'])
|
||||||
|
|
||||||
|
if not fallback_library_path:
|
||||||
|
for path in DEFAULT_LIBRARY_FALLBACK:
|
||||||
|
yield os.path.join(path, os.path.basename(name))
|
||||||
|
|
||||||
|
def dyld_find(name, executable_path=None, env=None):
|
||||||
|
"""
|
||||||
|
Find a library or framework using dyld semantics
|
||||||
|
"""
|
||||||
|
name = ensure_utf8(name)
|
||||||
|
executable_path = ensure_utf8(executable_path)
|
||||||
|
for path in dyld_image_suffix_search(chain(
|
||||||
|
dyld_override_search(name, env),
|
||||||
|
dyld_executable_path_search(name, executable_path),
|
||||||
|
dyld_default_search(name, env),
|
||||||
|
), env):
|
||||||
|
if os.path.isfile(path):
|
||||||
|
return path
|
||||||
|
raise ValueError, "dylib %s could not be found" % (name,)
|
||||||
|
|
||||||
|
def framework_find(fn, executable_path=None, env=None):
|
||||||
|
"""
|
||||||
|
Find a framework using dyld semantics in a very loose manner.
|
||||||
|
|
||||||
|
Will take input such as:
|
||||||
|
Python
|
||||||
|
Python.framework
|
||||||
|
Python.framework/Versions/Current
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return dyld_find(fn, executable_path=executable_path, env=env)
|
||||||
|
except ValueError, e:
|
||||||
|
pass
|
||||||
|
fmwk_index = fn.rfind('.framework')
|
||||||
|
if fmwk_index == -1:
|
||||||
|
fmwk_index = len(fn)
|
||||||
|
fn += '.framework'
|
||||||
|
fn = os.path.join(fn, os.path.basename(fn[:fmwk_index]))
|
||||||
|
try:
|
||||||
|
return dyld_find(fn, executable_path=executable_path, env=env)
|
||||||
|
except ValueError:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def test_dyld_find():
|
||||||
|
env = {}
|
||||||
|
assert dyld_find('libSystem.dylib') == '/usr/lib/libSystem.dylib'
|
||||||
|
assert dyld_find('System.framework/System') == '/System/Library/Frameworks/System.framework/System'
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_dyld_find()
|
||||||
63
Lib/ctypes/macholib/dylib.py
Normal file
63
Lib/ctypes/macholib/dylib.py
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
"""
|
||||||
|
Generic dylib path manipulation
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
__all__ = ['dylib_info']
|
||||||
|
|
||||||
|
DYLIB_RE = re.compile(r"""(?x)
|
||||||
|
(?P<location>^.*)(?:^|/)
|
||||||
|
(?P<name>
|
||||||
|
(?P<shortname>\w+?)
|
||||||
|
(?:\.(?P<version>[^._]+))?
|
||||||
|
(?:_(?P<suffix>[^._]+))?
|
||||||
|
\.dylib$
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
def dylib_info(filename):
|
||||||
|
"""
|
||||||
|
A dylib name can take one of the following four forms:
|
||||||
|
Location/Name.SomeVersion_Suffix.dylib
|
||||||
|
Location/Name.SomeVersion.dylib
|
||||||
|
Location/Name_Suffix.dylib
|
||||||
|
Location/Name.dylib
|
||||||
|
|
||||||
|
returns None if not found or a mapping equivalent to:
|
||||||
|
dict(
|
||||||
|
location='Location',
|
||||||
|
name='Name.SomeVersion_Suffix.dylib',
|
||||||
|
shortname='Name',
|
||||||
|
version='SomeVersion',
|
||||||
|
suffix='Suffix',
|
||||||
|
)
|
||||||
|
|
||||||
|
Note that SomeVersion and Suffix are optional and may be None
|
||||||
|
if not present.
|
||||||
|
"""
|
||||||
|
is_dylib = DYLIB_RE.match(filename)
|
||||||
|
if not is_dylib:
|
||||||
|
return None
|
||||||
|
return is_dylib.groupdict()
|
||||||
|
|
||||||
|
|
||||||
|
def test_dylib_info():
|
||||||
|
def d(location=None, name=None, shortname=None, version=None, suffix=None):
|
||||||
|
return dict(
|
||||||
|
location=location,
|
||||||
|
name=name,
|
||||||
|
shortname=shortname,
|
||||||
|
version=version,
|
||||||
|
suffix=suffix
|
||||||
|
)
|
||||||
|
assert dylib_info('completely/invalid') is None
|
||||||
|
assert dylib_info('completely/invalide_debug') is None
|
||||||
|
assert dylib_info('P/Foo.dylib') == d('P', 'Foo.dylib', 'Foo')
|
||||||
|
assert dylib_info('P/Foo_debug.dylib') == d('P', 'Foo_debug.dylib', 'Foo', suffix='debug')
|
||||||
|
assert dylib_info('P/Foo.A.dylib') == d('P', 'Foo.A.dylib', 'Foo', 'A')
|
||||||
|
assert dylib_info('P/Foo_debug.A.dylib') == d('P', 'Foo_debug.A.dylib', 'Foo_debug', 'A')
|
||||||
|
assert dylib_info('P/Foo.A_debug.dylib') == d('P', 'Foo.A_debug.dylib', 'Foo', 'A', 'debug')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_dylib_info()
|
||||||
2
Lib/ctypes/macholib/fetch_macholib
Executable file
2
Lib/ctypes/macholib/fetch_macholib
Executable file
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/sh
|
||||||
|
svn export --force http://svn.red-bean.com/bob/macholib/trunk/macholib/ .
|
||||||
1
Lib/ctypes/macholib/fetch_macholib.bat
Normal file
1
Lib/ctypes/macholib/fetch_macholib.bat
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
svn export --force http://svn.red-bean.com/bob/macholib/trunk/macholib/ .
|
||||||
65
Lib/ctypes/macholib/framework.py
Normal file
65
Lib/ctypes/macholib/framework.py
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
"""
|
||||||
|
Generic framework path manipulation
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
__all__ = ['framework_info']
|
||||||
|
|
||||||
|
STRICT_FRAMEWORK_RE = re.compile(r"""(?x)
|
||||||
|
(?P<location>^.*)(?:^|/)
|
||||||
|
(?P<name>
|
||||||
|
(?P<shortname>\w+).framework/
|
||||||
|
(?:Versions/(?P<version>[^/]+)/)?
|
||||||
|
(?P=shortname)
|
||||||
|
(?:_(?P<suffix>[^_]+))?
|
||||||
|
)$
|
||||||
|
""")
|
||||||
|
|
||||||
|
def framework_info(filename):
|
||||||
|
"""
|
||||||
|
A framework name can take one of the following four forms:
|
||||||
|
Location/Name.framework/Versions/SomeVersion/Name_Suffix
|
||||||
|
Location/Name.framework/Versions/SomeVersion/Name
|
||||||
|
Location/Name.framework/Name_Suffix
|
||||||
|
Location/Name.framework/Name
|
||||||
|
|
||||||
|
returns None if not found, or a mapping equivalent to:
|
||||||
|
dict(
|
||||||
|
location='Location',
|
||||||
|
name='Name.framework/Versions/SomeVersion/Name_Suffix',
|
||||||
|
shortname='Name',
|
||||||
|
version='SomeVersion',
|
||||||
|
suffix='Suffix',
|
||||||
|
)
|
||||||
|
|
||||||
|
Note that SomeVersion and Suffix are optional and may be None
|
||||||
|
if not present
|
||||||
|
"""
|
||||||
|
is_framework = STRICT_FRAMEWORK_RE.match(filename)
|
||||||
|
if not is_framework:
|
||||||
|
return None
|
||||||
|
return is_framework.groupdict()
|
||||||
|
|
||||||
|
def test_framework_info():
|
||||||
|
def d(location=None, name=None, shortname=None, version=None, suffix=None):
|
||||||
|
return dict(
|
||||||
|
location=location,
|
||||||
|
name=name,
|
||||||
|
shortname=shortname,
|
||||||
|
version=version,
|
||||||
|
suffix=suffix
|
||||||
|
)
|
||||||
|
assert framework_info('completely/invalid') is None
|
||||||
|
assert framework_info('completely/invalid/_debug') is None
|
||||||
|
assert framework_info('P/F.framework') is None
|
||||||
|
assert framework_info('P/F.framework/_debug') is None
|
||||||
|
assert framework_info('P/F.framework/F') == d('P', 'F.framework/F', 'F')
|
||||||
|
assert framework_info('P/F.framework/F_debug') == d('P', 'F.framework/F_debug', 'F', suffix='debug')
|
||||||
|
assert framework_info('P/F.framework/Versions') is None
|
||||||
|
assert framework_info('P/F.framework/Versions/A') is None
|
||||||
|
assert framework_info('P/F.framework/Versions/A/F') == d('P', 'F.framework/Versions/A/F', 'F', 'A')
|
||||||
|
assert framework_info('P/F.framework/Versions/A/F_debug') == d('P', 'F.framework/Versions/A/F_debug', 'F', 'A', 'debug')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_framework_info()
|
||||||
4
Lib/ctypes/test/.cvsignore
Normal file
4
Lib/ctypes/test/.cvsignore
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
_testfile.py
|
||||||
|
_testfile.xml
|
||||||
202
Lib/ctypes/test/__init__.py
Normal file
202
Lib/ctypes/test/__init__.py
Normal file
|
|
@ -0,0 +1,202 @@
|
||||||
|
import glob, os, sys, unittest, getopt, time
|
||||||
|
|
||||||
|
use_resources = []
|
||||||
|
|
||||||
|
class ResourceDenied(Exception):
|
||||||
|
"""Test skipped because it requested a disallowed resource.
|
||||||
|
|
||||||
|
This is raised when a test calls requires() for a resource that
|
||||||
|
has not be enabled. Resources are defined by test modules.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def is_resource_enabled(resource):
|
||||||
|
"""Test whether a resource is enabled.
|
||||||
|
|
||||||
|
If the caller's module is __main__ then automatically return True."""
|
||||||
|
if sys._getframe().f_back.f_globals.get("__name__") == "__main__":
|
||||||
|
return True
|
||||||
|
result = use_resources is not None and \
|
||||||
|
(resource in use_resources or "*" in use_resources)
|
||||||
|
if not result:
|
||||||
|
_unavail[resource] = None
|
||||||
|
return result
|
||||||
|
|
||||||
|
_unavail = {}
|
||||||
|
def requires(resource, msg=None):
|
||||||
|
"""Raise ResourceDenied if the specified resource is not available.
|
||||||
|
|
||||||
|
If the caller's module is __main__ then automatically return True."""
|
||||||
|
# see if the caller's module is __main__ - if so, treat as if
|
||||||
|
# the resource was set
|
||||||
|
if sys._getframe().f_back.f_globals.get("__name__") == "__main__":
|
||||||
|
return
|
||||||
|
if not is_resource_enabled(resource):
|
||||||
|
if msg is None:
|
||||||
|
msg = "Use of the `%s' resource not enabled" % resource
|
||||||
|
raise ResourceDenied(msg)
|
||||||
|
|
||||||
|
def find_package_modules(package, mask):
|
||||||
|
import fnmatch
|
||||||
|
if hasattr(package, "__loader__"):
|
||||||
|
path = package.__name__.replace(".", os.path.sep)
|
||||||
|
mask = os.path.join(path, mask)
|
||||||
|
for fnm in package.__loader__._files.iterkeys():
|
||||||
|
if fnmatch.fnmatchcase(fnm, mask):
|
||||||
|
yield os.path.splitext(fnm)[0].replace(os.path.sep, ".")
|
||||||
|
else:
|
||||||
|
path = package.__path__[0]
|
||||||
|
for fnm in os.listdir(path):
|
||||||
|
if fnmatch.fnmatchcase(fnm, mask):
|
||||||
|
yield "%s.%s" % (package.__name__, os.path.splitext(fnm)[0])
|
||||||
|
|
||||||
|
def get_tests(package, mask, verbosity):
|
||||||
|
"""Return a list of skipped test modules, and a list of test cases."""
|
||||||
|
tests = []
|
||||||
|
skipped = []
|
||||||
|
for modname in find_package_modules(package, mask):
|
||||||
|
try:
|
||||||
|
mod = __import__(modname, globals(), locals(), ['*'])
|
||||||
|
except ResourceDenied, detail:
|
||||||
|
skipped.append(modname)
|
||||||
|
if verbosity > 1:
|
||||||
|
print >> sys.stderr, "Skipped %s: %s" % (modname, detail)
|
||||||
|
continue
|
||||||
|
except Exception, detail:
|
||||||
|
print >> sys.stderr, "Warning: could not import %s: %s" % (modname, detail)
|
||||||
|
continue
|
||||||
|
for name in dir(mod):
|
||||||
|
if name.startswith("_"):
|
||||||
|
continue
|
||||||
|
o = getattr(mod, name)
|
||||||
|
if type(o) is type(unittest.TestCase) and issubclass(o, unittest.TestCase):
|
||||||
|
tests.append(o)
|
||||||
|
return skipped, tests
|
||||||
|
|
||||||
|
def usage():
|
||||||
|
print __doc__
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def test_with_refcounts(runner, verbosity, testcase):
|
||||||
|
"""Run testcase several times, tracking reference counts."""
|
||||||
|
import gc
|
||||||
|
import ctypes
|
||||||
|
ptc = ctypes._pointer_type_cache.copy()
|
||||||
|
cfc = ctypes._c_functype_cache.copy()
|
||||||
|
wfc = ctypes._win_functype_cache.copy()
|
||||||
|
|
||||||
|
# when searching for refcount leaks, we have to manually reset any
|
||||||
|
# caches that ctypes has.
|
||||||
|
def cleanup():
|
||||||
|
ctypes._pointer_type_cache = ptc.copy()
|
||||||
|
ctypes._c_functype_cache = cfc.copy()
|
||||||
|
ctypes._win_functype_cache = wfc.copy()
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
test = unittest.makeSuite(testcase)
|
||||||
|
for i in range(5):
|
||||||
|
rc = sys.gettotalrefcount()
|
||||||
|
runner.run(test)
|
||||||
|
cleanup()
|
||||||
|
COUNT = 5
|
||||||
|
refcounts = [None] * COUNT
|
||||||
|
for i in range(COUNT):
|
||||||
|
rc = sys.gettotalrefcount()
|
||||||
|
runner.run(test)
|
||||||
|
cleanup()
|
||||||
|
refcounts[i] = sys.gettotalrefcount() - rc
|
||||||
|
if filter(None, refcounts):
|
||||||
|
print "%s leaks:\n\t" % testcase, refcounts
|
||||||
|
elif verbosity:
|
||||||
|
print "%s: ok." % testcase
|
||||||
|
|
||||||
|
class TestRunner(unittest.TextTestRunner):
|
||||||
|
def run(self, test, skipped):
|
||||||
|
"Run the given test case or test suite."
|
||||||
|
# Same as unittest.TextTestRunner.run, except that it reports
|
||||||
|
# skipped tests.
|
||||||
|
result = self._makeResult()
|
||||||
|
startTime = time.time()
|
||||||
|
test(result)
|
||||||
|
stopTime = time.time()
|
||||||
|
timeTaken = stopTime - startTime
|
||||||
|
result.printErrors()
|
||||||
|
self.stream.writeln(result.separator2)
|
||||||
|
run = result.testsRun
|
||||||
|
if _unavail: #skipped:
|
||||||
|
requested = _unavail.keys()
|
||||||
|
requested.sort()
|
||||||
|
self.stream.writeln("Ran %d test%s in %.3fs (%s module%s skipped)" %
|
||||||
|
(run, run != 1 and "s" or "", timeTaken,
|
||||||
|
len(skipped),
|
||||||
|
len(skipped) != 1 and "s" or ""))
|
||||||
|
self.stream.writeln("Unavailable resources: %s" % ", ".join(requested))
|
||||||
|
else:
|
||||||
|
self.stream.writeln("Ran %d test%s in %.3fs" %
|
||||||
|
(run, run != 1 and "s" or "", timeTaken))
|
||||||
|
self.stream.writeln()
|
||||||
|
if not result.wasSuccessful():
|
||||||
|
self.stream.write("FAILED (")
|
||||||
|
failed, errored = map(len, (result.failures, result.errors))
|
||||||
|
if failed:
|
||||||
|
self.stream.write("failures=%d" % failed)
|
||||||
|
if errored:
|
||||||
|
if failed: self.stream.write(", ")
|
||||||
|
self.stream.write("errors=%d" % errored)
|
||||||
|
self.stream.writeln(")")
|
||||||
|
else:
|
||||||
|
self.stream.writeln("OK")
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def main(*packages):
|
||||||
|
try:
|
||||||
|
opts, args = getopt.getopt(sys.argv[1:], "rqvu:")
|
||||||
|
except getopt.error:
|
||||||
|
return usage()
|
||||||
|
|
||||||
|
verbosity = 1
|
||||||
|
search_leaks = False
|
||||||
|
for flag, value in opts:
|
||||||
|
if flag == "-q":
|
||||||
|
verbosity -= 1
|
||||||
|
elif flag == "-v":
|
||||||
|
verbosity += 1
|
||||||
|
elif flag == "-r":
|
||||||
|
try:
|
||||||
|
sys.gettotalrefcount
|
||||||
|
except AttributeError:
|
||||||
|
print >> sys.stderr, "-r flag requires Python debug build"
|
||||||
|
return -1
|
||||||
|
search_leaks = True
|
||||||
|
elif flag == "-u":
|
||||||
|
use_resources.extend(value.split(","))
|
||||||
|
|
||||||
|
mask = "test_*.py"
|
||||||
|
if args:
|
||||||
|
mask = args[0]
|
||||||
|
|
||||||
|
for package in packages:
|
||||||
|
run_tests(package, mask, verbosity, search_leaks)
|
||||||
|
|
||||||
|
|
||||||
|
def run_tests(package, mask, verbosity, search_leaks):
|
||||||
|
skipped, testcases = get_tests(package, mask, verbosity)
|
||||||
|
runner = TestRunner(verbosity=verbosity)
|
||||||
|
|
||||||
|
suites = [unittest.makeSuite(o) for o in testcases]
|
||||||
|
suite = unittest.TestSuite(suites)
|
||||||
|
result = runner.run(suite, skipped)
|
||||||
|
|
||||||
|
if search_leaks:
|
||||||
|
# hunt for refcount leaks
|
||||||
|
runner = BasicTestRunner()
|
||||||
|
for t in testcases:
|
||||||
|
test_with_refcounts(runner, verbosity, t)
|
||||||
|
|
||||||
|
return bool(result.errors)
|
||||||
|
|
||||||
|
class BasicTestRunner:
|
||||||
|
def run(self, test):
|
||||||
|
result = unittest.TestResult()
|
||||||
|
test(result)
|
||||||
|
return result
|
||||||
17
Lib/ctypes/test/runtests.py
Normal file
17
Lib/ctypes/test/runtests.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
"""Usage: runtests.py [-q] [-r] [-v] [-u resources] [mask]
|
||||||
|
|
||||||
|
Run all tests found in this directory, and print a summary of the results.
|
||||||
|
Command line flags:
|
||||||
|
-q quiet mode: don't prnt anything while the tests are running
|
||||||
|
-r run tests repeatedly, look for refcount leaks
|
||||||
|
-u<resources>
|
||||||
|
Add resources to the lits of allowed resources. '*' allows all
|
||||||
|
resources.
|
||||||
|
-v verbose mode: print the test currently executed
|
||||||
|
mask mask to select filenames containing testcases, wildcards allowed
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
import ctypes.test
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(ctypes.test.main(ctypes.test))
|
||||||
64
Lib/ctypes/test/test_array_in_pointer.py
Normal file
64
Lib/ctypes/test/test_array_in_pointer.py
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
from binascii import hexlify
|
||||||
|
import re
|
||||||
|
|
||||||
|
def dump(obj):
|
||||||
|
# helper function to dump memory contents in hex, with a hyphen
|
||||||
|
# between the bytes.
|
||||||
|
h = hexlify(buffer(obj))
|
||||||
|
return re.sub(r"(..)", r"\1-", h)[:-1]
|
||||||
|
|
||||||
|
|
||||||
|
class Value(Structure):
|
||||||
|
_fields_ = [("val", c_byte)]
|
||||||
|
|
||||||
|
class Container(Structure):
|
||||||
|
_fields_ = [("pvalues", POINTER(Value))]
|
||||||
|
|
||||||
|
class Test(unittest.TestCase):
|
||||||
|
def test(self):
|
||||||
|
# create an array of 4 values
|
||||||
|
val_array = (Value * 4)()
|
||||||
|
|
||||||
|
# create a container, which holds a pointer to the pvalues array.
|
||||||
|
c = Container()
|
||||||
|
c.pvalues = val_array
|
||||||
|
|
||||||
|
# memory contains 4 NUL bytes now, that's correct
|
||||||
|
self.failUnlessEqual("00-00-00-00", dump(val_array))
|
||||||
|
|
||||||
|
# set the values of the array through the pointer:
|
||||||
|
for i in range(4):
|
||||||
|
c.pvalues[i].val = i + 1
|
||||||
|
|
||||||
|
values = [c.pvalues[i].val for i in range(4)]
|
||||||
|
|
||||||
|
# These are the expected results: here s the bug!
|
||||||
|
self.failUnlessEqual(
|
||||||
|
(values, dump(val_array)),
|
||||||
|
([1, 2, 3, 4], "01-02-03-04")
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_2(self):
|
||||||
|
|
||||||
|
val_array = (Value * 4)()
|
||||||
|
|
||||||
|
# memory contains 4 NUL bytes now, that's correct
|
||||||
|
self.failUnlessEqual("00-00-00-00", dump(val_array))
|
||||||
|
|
||||||
|
ptr = cast(val_array, POINTER(Value))
|
||||||
|
# set the values of the array through the pointer:
|
||||||
|
for i in range(4):
|
||||||
|
ptr[i].val = i + 1
|
||||||
|
|
||||||
|
values = [ptr[i].val for i in range(4)]
|
||||||
|
|
||||||
|
# These are the expected results: here s the bug!
|
||||||
|
self.failUnlessEqual(
|
||||||
|
(values, dump(val_array)),
|
||||||
|
([1, 2, 3, 4], "01-02-03-04")
|
||||||
|
)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
112
Lib/ctypes/test/test_arrays.py
Normal file
112
Lib/ctypes/test/test_arrays.py
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
formats = "bBhHiIlLqQfd"
|
||||||
|
|
||||||
|
formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \
|
||||||
|
c_long, c_ulonglong, c_float, c_double
|
||||||
|
|
||||||
|
class ArrayTestCase(unittest.TestCase):
|
||||||
|
def test_simple(self):
|
||||||
|
# create classes holding simple numeric types, and check
|
||||||
|
# various properties.
|
||||||
|
|
||||||
|
init = range(15, 25)
|
||||||
|
|
||||||
|
for fmt in formats:
|
||||||
|
alen = len(init)
|
||||||
|
int_array = ARRAY(fmt, alen)
|
||||||
|
|
||||||
|
ia = int_array(*init)
|
||||||
|
# length of instance ok?
|
||||||
|
self.failUnlessEqual(len(ia), alen)
|
||||||
|
|
||||||
|
# slot values ok?
|
||||||
|
values = [ia[i] for i in range(len(init))]
|
||||||
|
self.failUnlessEqual(values, init)
|
||||||
|
|
||||||
|
# change the items
|
||||||
|
from operator import setitem
|
||||||
|
new_values = range(42, 42+alen)
|
||||||
|
[setitem(ia, n, new_values[n]) for n in range(alen)]
|
||||||
|
values = [ia[i] for i in range(len(init))]
|
||||||
|
self.failUnlessEqual(values, new_values)
|
||||||
|
|
||||||
|
# are the items initialized to 0?
|
||||||
|
ia = int_array()
|
||||||
|
values = [ia[i] for i in range(len(init))]
|
||||||
|
self.failUnlessEqual(values, [0] * len(init))
|
||||||
|
|
||||||
|
# Too many in itializers should be caught
|
||||||
|
self.assertRaises(IndexError, int_array, *range(alen*2))
|
||||||
|
|
||||||
|
CharArray = ARRAY(c_char, 3)
|
||||||
|
|
||||||
|
ca = CharArray("a", "b", "c")
|
||||||
|
|
||||||
|
# Should this work? It doesn't:
|
||||||
|
# CharArray("abc")
|
||||||
|
self.assertRaises(TypeError, CharArray, "abc")
|
||||||
|
|
||||||
|
self.failUnlessEqual(ca[0], "a")
|
||||||
|
self.failUnlessEqual(ca[1], "b")
|
||||||
|
self.failUnlessEqual(ca[2], "c")
|
||||||
|
self.failUnlessEqual(ca[-3], "a")
|
||||||
|
self.failUnlessEqual(ca[-2], "b")
|
||||||
|
self.failUnlessEqual(ca[-1], "c")
|
||||||
|
|
||||||
|
self.failUnlessEqual(len(ca), 3)
|
||||||
|
|
||||||
|
# slicing is now supported, but not extended slicing (3-argument)!
|
||||||
|
from operator import getslice, delitem
|
||||||
|
self.assertRaises(TypeError, getslice, ca, 0, 1, -1)
|
||||||
|
|
||||||
|
# cannot delete items
|
||||||
|
self.assertRaises(TypeError, delitem, ca, 0)
|
||||||
|
|
||||||
|
def test_numeric_arrays(self):
|
||||||
|
|
||||||
|
alen = 5
|
||||||
|
|
||||||
|
numarray = ARRAY(c_int, alen)
|
||||||
|
|
||||||
|
na = numarray()
|
||||||
|
values = [na[i] for i in range(alen)]
|
||||||
|
self.failUnlessEqual(values, [0] * alen)
|
||||||
|
|
||||||
|
na = numarray(*[c_int()] * alen)
|
||||||
|
values = [na[i] for i in range(alen)]
|
||||||
|
self.failUnlessEqual(values, [0]*alen)
|
||||||
|
|
||||||
|
na = numarray(1, 2, 3, 4, 5)
|
||||||
|
values = [i for i in na]
|
||||||
|
self.failUnlessEqual(values, [1, 2, 3, 4, 5])
|
||||||
|
|
||||||
|
na = numarray(*map(c_int, (1, 2, 3, 4, 5)))
|
||||||
|
values = [i for i in na]
|
||||||
|
self.failUnlessEqual(values, [1, 2, 3, 4, 5])
|
||||||
|
|
||||||
|
def test_classcache(self):
|
||||||
|
self.failUnless(not ARRAY(c_int, 3) is ARRAY(c_int, 4))
|
||||||
|
self.failUnless(ARRAY(c_int, 3) is ARRAY(c_int, 3))
|
||||||
|
|
||||||
|
def test_from_address(self):
|
||||||
|
# Failed with 0.9.8, reported by JUrner
|
||||||
|
p = create_string_buffer("foo")
|
||||||
|
sz = (c_char * 3).from_address(addressof(p))
|
||||||
|
self.failUnlessEqual(sz[:], "foo")
|
||||||
|
self.failUnlessEqual(sz.value, "foo")
|
||||||
|
|
||||||
|
try:
|
||||||
|
create_unicode_buffer
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
def test_from_addressW(self):
|
||||||
|
p = create_unicode_buffer("foo")
|
||||||
|
sz = (c_wchar * 3).from_address(addressof(p))
|
||||||
|
self.failUnlessEqual(sz[:], "foo")
|
||||||
|
self.failUnlessEqual(sz.value, "foo")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
219
Lib/ctypes/test/test_bitfields.py
Normal file
219
Lib/ctypes/test/test_bitfields.py
Normal file
|
|
@ -0,0 +1,219 @@
|
||||||
|
from ctypes import *
|
||||||
|
import unittest
|
||||||
|
import os
|
||||||
|
|
||||||
|
import ctypes
|
||||||
|
import _ctypes_test
|
||||||
|
|
||||||
|
class BITS(Structure):
|
||||||
|
_fields_ = [("A", c_int, 1),
|
||||||
|
("B", c_int, 2),
|
||||||
|
("C", c_int, 3),
|
||||||
|
("D", c_int, 4),
|
||||||
|
("E", c_int, 5),
|
||||||
|
("F", c_int, 6),
|
||||||
|
("G", c_int, 7),
|
||||||
|
("H", c_int, 8),
|
||||||
|
("I", c_int, 9),
|
||||||
|
|
||||||
|
("M", c_short, 1),
|
||||||
|
("N", c_short, 2),
|
||||||
|
("O", c_short, 3),
|
||||||
|
("P", c_short, 4),
|
||||||
|
("Q", c_short, 5),
|
||||||
|
("R", c_short, 6),
|
||||||
|
("S", c_short, 7)]
|
||||||
|
|
||||||
|
func = cdll.load(_ctypes_test.__file__).unpack_bitfields
|
||||||
|
func.argtypes = POINTER(BITS), c_char
|
||||||
|
|
||||||
|
##for n in "ABCDEFGHIMNOPQRS":
|
||||||
|
## print n, hex(getattr(BITS, n).size), getattr(BITS, n).offset
|
||||||
|
|
||||||
|
class C_Test(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_ints(self):
|
||||||
|
for i in range(512):
|
||||||
|
for name in "ABCDEFGHI":
|
||||||
|
b = BITS()
|
||||||
|
setattr(b, name, i)
|
||||||
|
self.failUnlessEqual((name, i, getattr(b, name)), (name, i, func(byref(b), name)))
|
||||||
|
|
||||||
|
def test_shorts(self):
|
||||||
|
for i in range(256):
|
||||||
|
for name in "MNOPQRS":
|
||||||
|
b = BITS()
|
||||||
|
setattr(b, name, i)
|
||||||
|
self.failUnlessEqual((name, i, getattr(b, name)), (name, i, func(byref(b), name)))
|
||||||
|
|
||||||
|
signed_int_types = (c_byte, c_short, c_int, c_long, c_longlong)
|
||||||
|
unsigned_int_types = (c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong)
|
||||||
|
int_types = unsigned_int_types + signed_int_types
|
||||||
|
|
||||||
|
class BitFieldTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_longlong(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_longlong, 1),
|
||||||
|
("b", c_longlong, 62),
|
||||||
|
("c", c_longlong, 1)]
|
||||||
|
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_longlong))
|
||||||
|
x = X()
|
||||||
|
x.a, x.b, x.c = -1, 7, -1
|
||||||
|
self.failUnlessEqual((x.a, x.b, x.c), (-1, 7, -1))
|
||||||
|
|
||||||
|
def test_ulonglong(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_ulonglong, 1),
|
||||||
|
("b", c_ulonglong, 62),
|
||||||
|
("c", c_ulonglong, 1)]
|
||||||
|
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_longlong))
|
||||||
|
x = X()
|
||||||
|
self.failUnlessEqual((x.a, x.b, x.c), (0, 0, 0))
|
||||||
|
x.a, x.b, x.c = 7, 7, 7
|
||||||
|
self.failUnlessEqual((x.a, x.b, x.c), (1, 7, 1))
|
||||||
|
|
||||||
|
def test_signed(self):
|
||||||
|
for c_typ in signed_int_types:
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("dummy", c_typ),
|
||||||
|
("a", c_typ, 3),
|
||||||
|
("b", c_typ, 3),
|
||||||
|
("c", c_typ, 1)]
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_typ)*2)
|
||||||
|
|
||||||
|
x = X()
|
||||||
|
self.failUnlessEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 0, 0))
|
||||||
|
x.a = -1
|
||||||
|
self.failUnlessEqual((c_typ, x.a, x.b, x.c), (c_typ, -1, 0, 0))
|
||||||
|
x.a, x.b = 0, -1
|
||||||
|
self.failUnlessEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, -1, 0))
|
||||||
|
|
||||||
|
|
||||||
|
def test_unsigned(self):
|
||||||
|
for c_typ in unsigned_int_types:
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_typ, 3),
|
||||||
|
("b", c_typ, 3),
|
||||||
|
("c", c_typ, 1)]
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_typ))
|
||||||
|
|
||||||
|
x = X()
|
||||||
|
self.failUnlessEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 0, 0))
|
||||||
|
x.a = -1
|
||||||
|
self.failUnlessEqual((c_typ, x.a, x.b, x.c), (c_typ, 7, 0, 0))
|
||||||
|
x.a, x.b = 0, -1
|
||||||
|
self.failUnlessEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 7, 0))
|
||||||
|
|
||||||
|
|
||||||
|
def fail_fields(self, *fields):
|
||||||
|
return self.get_except(type(Structure), "X", (),
|
||||||
|
{"_fields_": fields})
|
||||||
|
|
||||||
|
def test_nonint_types(self):
|
||||||
|
# bit fields are not allowed on non-integer types.
|
||||||
|
result = self.fail_fields(("a", c_char_p, 1))
|
||||||
|
self.failUnlessEqual(result, (TypeError, 'bit fields not allowed for type c_char_p'))
|
||||||
|
|
||||||
|
result = self.fail_fields(("a", c_void_p, 1))
|
||||||
|
self.failUnlessEqual(result, (TypeError, 'bit fields not allowed for type c_void_p'))
|
||||||
|
|
||||||
|
if c_int != c_long:
|
||||||
|
result = self.fail_fields(("a", POINTER(c_int), 1))
|
||||||
|
self.failUnlessEqual(result, (TypeError, 'bit fields not allowed for type LP_c_int'))
|
||||||
|
|
||||||
|
result = self.fail_fields(("a", c_char, 1))
|
||||||
|
self.failUnlessEqual(result, (TypeError, 'bit fields not allowed for type c_char'))
|
||||||
|
|
||||||
|
try:
|
||||||
|
c_wchar
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
result = self.fail_fields(("a", c_wchar, 1))
|
||||||
|
self.failUnlessEqual(result, (TypeError, 'bit fields not allowed for type c_wchar'))
|
||||||
|
|
||||||
|
class Dummy(Structure):
|
||||||
|
_fields_ = []
|
||||||
|
|
||||||
|
result = self.fail_fields(("a", Dummy, 1))
|
||||||
|
self.failUnlessEqual(result, (TypeError, 'bit fields not allowed for type Dummy'))
|
||||||
|
|
||||||
|
def test_single_bitfield_size(self):
|
||||||
|
for c_typ in int_types:
|
||||||
|
result = self.fail_fields(("a", c_typ, -1))
|
||||||
|
self.failUnlessEqual(result, (ValueError, 'number of bits invalid for bit field'))
|
||||||
|
|
||||||
|
result = self.fail_fields(("a", c_typ, 0))
|
||||||
|
self.failUnlessEqual(result, (ValueError, 'number of bits invalid for bit field'))
|
||||||
|
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_typ, 1)]
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_typ))
|
||||||
|
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_typ, sizeof(c_typ)*8)]
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_typ))
|
||||||
|
|
||||||
|
result = self.fail_fields(("a", c_typ, sizeof(c_typ)*8 + 1))
|
||||||
|
self.failUnlessEqual(result, (ValueError, 'number of bits invalid for bit field'))
|
||||||
|
|
||||||
|
def test_multi_bitfields_size(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_short, 1),
|
||||||
|
("b", c_short, 14),
|
||||||
|
("c", c_short, 1)]
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_short))
|
||||||
|
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_short, 1),
|
||||||
|
("a1", c_short),
|
||||||
|
("b", c_short, 14),
|
||||||
|
("c", c_short, 1)]
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_short)*3)
|
||||||
|
self.failUnlessEqual(X.a.offset, 0)
|
||||||
|
self.failUnlessEqual(X.a1.offset, sizeof(c_short))
|
||||||
|
self.failUnlessEqual(X.b.offset, sizeof(c_short)*2)
|
||||||
|
self.failUnlessEqual(X.c.offset, sizeof(c_short)*2)
|
||||||
|
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_short, 3),
|
||||||
|
("b", c_short, 14),
|
||||||
|
("c", c_short, 14)]
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_short)*3)
|
||||||
|
self.failUnlessEqual(X.a.offset, sizeof(c_short)*0)
|
||||||
|
self.failUnlessEqual(X.b.offset, sizeof(c_short)*1)
|
||||||
|
self.failUnlessEqual(X.c.offset, sizeof(c_short)*2)
|
||||||
|
|
||||||
|
|
||||||
|
def get_except(self, func, *args, **kw):
|
||||||
|
try:
|
||||||
|
func(*args, **kw)
|
||||||
|
except Exception, detail:
|
||||||
|
return detail.__class__, str(detail)
|
||||||
|
|
||||||
|
def test_mixed_1(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_byte, 4),
|
||||||
|
("b", c_int, 4)]
|
||||||
|
if os.name in ("nt", "ce"):
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_int)*2)
|
||||||
|
else:
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_int))
|
||||||
|
|
||||||
|
def test_mixed_2(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_byte, 4),
|
||||||
|
("b", c_int, 32)]
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_int)*2)
|
||||||
|
|
||||||
|
def test_mixed_3(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_byte, 4),
|
||||||
|
("b", c_ubyte, 4)]
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_byte))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
54
Lib/ctypes/test/test_buffers.py
Normal file
54
Lib/ctypes/test/test_buffers.py
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
from ctypes import *
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class StringBufferTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_buffer(self):
|
||||||
|
b = create_string_buffer(32)
|
||||||
|
self.failUnlessEqual(len(b), 32)
|
||||||
|
self.failUnlessEqual(sizeof(b), 32 * sizeof(c_char))
|
||||||
|
self.failUnless(type(b[0]) is str)
|
||||||
|
|
||||||
|
b = create_string_buffer("abc")
|
||||||
|
self.failUnlessEqual(len(b), 4) # trailing nul char
|
||||||
|
self.failUnlessEqual(sizeof(b), 4 * sizeof(c_char))
|
||||||
|
self.failUnless(type(b[0]) is str)
|
||||||
|
self.failUnlessEqual(b[0], "a")
|
||||||
|
self.failUnlessEqual(b[:], "abc\0")
|
||||||
|
|
||||||
|
def test_string_conversion(self):
|
||||||
|
b = create_string_buffer(u"abc")
|
||||||
|
self.failUnlessEqual(len(b), 4) # trailing nul char
|
||||||
|
self.failUnlessEqual(sizeof(b), 4 * sizeof(c_char))
|
||||||
|
self.failUnless(type(b[0]) is str)
|
||||||
|
self.failUnlessEqual(b[0], "a")
|
||||||
|
self.failUnlessEqual(b[:], "abc\0")
|
||||||
|
|
||||||
|
try:
|
||||||
|
c_wchar
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
def test_unicode_buffer(self):
|
||||||
|
b = create_unicode_buffer(32)
|
||||||
|
self.failUnlessEqual(len(b), 32)
|
||||||
|
self.failUnlessEqual(sizeof(b), 32 * sizeof(c_wchar))
|
||||||
|
self.failUnless(type(b[0]) is unicode)
|
||||||
|
|
||||||
|
b = create_unicode_buffer(u"abc")
|
||||||
|
self.failUnlessEqual(len(b), 4) # trailing nul char
|
||||||
|
self.failUnlessEqual(sizeof(b), 4 * sizeof(c_wchar))
|
||||||
|
self.failUnless(type(b[0]) is unicode)
|
||||||
|
self.failUnlessEqual(b[0], u"a")
|
||||||
|
self.failUnlessEqual(b[:], "abc\0")
|
||||||
|
|
||||||
|
def test_unicode_conversion(self):
|
||||||
|
b = create_unicode_buffer("abc")
|
||||||
|
self.failUnlessEqual(len(b), 4) # trailing nul char
|
||||||
|
self.failUnlessEqual(sizeof(b), 4 * sizeof(c_wchar))
|
||||||
|
self.failUnless(type(b[0]) is unicode)
|
||||||
|
self.failUnlessEqual(b[0], u"a")
|
||||||
|
self.failUnlessEqual(b[:], "abc\0")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
221
Lib/ctypes/test/test_byteswap.py
Normal file
221
Lib/ctypes/test/test_byteswap.py
Normal file
|
|
@ -0,0 +1,221 @@
|
||||||
|
import sys, unittest, struct, math
|
||||||
|
from binascii import hexlify
|
||||||
|
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
def bin(s):
|
||||||
|
return hexlify(buffer(s)).upper()
|
||||||
|
|
||||||
|
# Each *simple* type that supports different byte orders has an
|
||||||
|
# __ctype_be__ attribute that specifies the same type in BIG ENDIAN
|
||||||
|
# byte order, and a __ctype_le__ attribute that is the same type in
|
||||||
|
# LITTLE ENDIAN byte order.
|
||||||
|
#
|
||||||
|
# For Structures and Unions, these types are created on demand.
|
||||||
|
|
||||||
|
class Test(unittest.TestCase):
|
||||||
|
def X_test(self):
|
||||||
|
print sys.byteorder
|
||||||
|
for i in range(32):
|
||||||
|
bits = BITS()
|
||||||
|
setattr(bits, "i%s" % i, 1)
|
||||||
|
dump(bits)
|
||||||
|
|
||||||
|
def test_endian_short(self):
|
||||||
|
if sys.byteorder == "little":
|
||||||
|
self.failUnless(c_short.__ctype_le__ is c_short)
|
||||||
|
self.failUnless(c_short.__ctype_be__.__ctype_le__ is c_short)
|
||||||
|
else:
|
||||||
|
self.failUnless(c_short.__ctype_be__ is c_short)
|
||||||
|
self.failUnless(c_short.__ctype_le__.__ctype_be__ is c_short)
|
||||||
|
s = c_short.__ctype_be__(0x1234)
|
||||||
|
self.failUnlessEqual(bin(struct.pack(">h", 0x1234)), "1234")
|
||||||
|
self.failUnlessEqual(bin(s), "1234")
|
||||||
|
self.failUnlessEqual(s.value, 0x1234)
|
||||||
|
|
||||||
|
s = c_short.__ctype_le__(0x1234)
|
||||||
|
self.failUnlessEqual(bin(struct.pack("<h", 0x1234)), "3412")
|
||||||
|
self.failUnlessEqual(bin(s), "3412")
|
||||||
|
self.failUnlessEqual(s.value, 0x1234)
|
||||||
|
|
||||||
|
s = c_ushort.__ctype_be__(0x1234)
|
||||||
|
self.failUnlessEqual(bin(struct.pack(">h", 0x1234)), "1234")
|
||||||
|
self.failUnlessEqual(bin(s), "1234")
|
||||||
|
self.failUnlessEqual(s.value, 0x1234)
|
||||||
|
|
||||||
|
s = c_ushort.__ctype_le__(0x1234)
|
||||||
|
self.failUnlessEqual(bin(struct.pack("<h", 0x1234)), "3412")
|
||||||
|
self.failUnlessEqual(bin(s), "3412")
|
||||||
|
self.failUnlessEqual(s.value, 0x1234)
|
||||||
|
|
||||||
|
def test_endian_int(self):
|
||||||
|
if sys.byteorder == "little":
|
||||||
|
self.failUnless(c_int.__ctype_le__ is c_int)
|
||||||
|
self.failUnless(c_int.__ctype_be__.__ctype_le__ is c_int)
|
||||||
|
else:
|
||||||
|
self.failUnless(c_int.__ctype_be__ is c_int)
|
||||||
|
self.failUnless(c_int.__ctype_le__.__ctype_be__ is c_int)
|
||||||
|
|
||||||
|
s = c_int.__ctype_be__(0x12345678)
|
||||||
|
self.failUnlessEqual(bin(struct.pack(">i", 0x12345678)), "12345678")
|
||||||
|
self.failUnlessEqual(bin(s), "12345678")
|
||||||
|
self.failUnlessEqual(s.value, 0x12345678)
|
||||||
|
|
||||||
|
s = c_int.__ctype_le__(0x12345678)
|
||||||
|
self.failUnlessEqual(bin(struct.pack("<i", 0x12345678)), "78563412")
|
||||||
|
self.failUnlessEqual(bin(s), "78563412")
|
||||||
|
self.failUnlessEqual(s.value, 0x12345678)
|
||||||
|
|
||||||
|
s = c_uint.__ctype_be__(0x12345678)
|
||||||
|
self.failUnlessEqual(bin(struct.pack(">I", 0x12345678)), "12345678")
|
||||||
|
self.failUnlessEqual(bin(s), "12345678")
|
||||||
|
self.failUnlessEqual(s.value, 0x12345678)
|
||||||
|
|
||||||
|
s = c_uint.__ctype_le__(0x12345678)
|
||||||
|
self.failUnlessEqual(bin(struct.pack("<I", 0x12345678)), "78563412")
|
||||||
|
self.failUnlessEqual(bin(s), "78563412")
|
||||||
|
self.failUnlessEqual(s.value, 0x12345678)
|
||||||
|
|
||||||
|
def test_endian_longlong(self):
|
||||||
|
if sys.byteorder == "little":
|
||||||
|
self.failUnless(c_longlong.__ctype_le__ is c_longlong)
|
||||||
|
self.failUnless(c_longlong.__ctype_be__.__ctype_le__ is c_longlong)
|
||||||
|
else:
|
||||||
|
self.failUnless(c_longlong.__ctype_be__ is c_longlong)
|
||||||
|
self.failUnless(c_longlong.__ctype_le__.__ctype_be__ is c_longlong)
|
||||||
|
|
||||||
|
s = c_longlong.__ctype_be__(0x1234567890ABCDEF)
|
||||||
|
self.failUnlessEqual(bin(struct.pack(">q", 0x1234567890ABCDEF)), "1234567890ABCDEF")
|
||||||
|
self.failUnlessEqual(bin(s), "1234567890ABCDEF")
|
||||||
|
self.failUnlessEqual(s.value, 0x1234567890ABCDEF)
|
||||||
|
|
||||||
|
s = c_longlong.__ctype_le__(0x1234567890ABCDEF)
|
||||||
|
self.failUnlessEqual(bin(struct.pack("<q", 0x1234567890ABCDEF)), "EFCDAB9078563412")
|
||||||
|
self.failUnlessEqual(bin(s), "EFCDAB9078563412")
|
||||||
|
self.failUnlessEqual(s.value, 0x1234567890ABCDEF)
|
||||||
|
|
||||||
|
s = c_ulonglong.__ctype_be__(0x1234567890ABCDEF)
|
||||||
|
self.failUnlessEqual(bin(struct.pack(">Q", 0x1234567890ABCDEF)), "1234567890ABCDEF")
|
||||||
|
self.failUnlessEqual(bin(s), "1234567890ABCDEF")
|
||||||
|
self.failUnlessEqual(s.value, 0x1234567890ABCDEF)
|
||||||
|
|
||||||
|
s = c_ulonglong.__ctype_le__(0x1234567890ABCDEF)
|
||||||
|
self.failUnlessEqual(bin(struct.pack("<Q", 0x1234567890ABCDEF)), "EFCDAB9078563412")
|
||||||
|
self.failUnlessEqual(bin(s), "EFCDAB9078563412")
|
||||||
|
self.failUnlessEqual(s.value, 0x1234567890ABCDEF)
|
||||||
|
|
||||||
|
def test_endian_float(self):
|
||||||
|
if sys.byteorder == "little":
|
||||||
|
self.failUnless(c_float.__ctype_le__ is c_float)
|
||||||
|
self.failUnless(c_float.__ctype_be__.__ctype_le__ is c_float)
|
||||||
|
else:
|
||||||
|
self.failUnless(c_float.__ctype_be__ is c_float)
|
||||||
|
self.failUnless(c_float.__ctype_le__.__ctype_be__ is c_float)
|
||||||
|
s = c_float(math.pi)
|
||||||
|
self.failUnlessEqual(bin(struct.pack("f", math.pi)), bin(s))
|
||||||
|
# Hm, what's the precision of a float compared to a double?
|
||||||
|
self.failUnlessAlmostEqual(s.value, math.pi, 6)
|
||||||
|
s = c_float.__ctype_le__(math.pi)
|
||||||
|
self.failUnlessAlmostEqual(s.value, math.pi, 6)
|
||||||
|
self.failUnlessEqual(bin(struct.pack("<f", math.pi)), bin(s))
|
||||||
|
s = c_float.__ctype_be__(math.pi)
|
||||||
|
self.failUnlessAlmostEqual(s.value, math.pi, 6)
|
||||||
|
self.failUnlessEqual(bin(struct.pack(">f", math.pi)), bin(s))
|
||||||
|
|
||||||
|
def test_endian_double(self):
|
||||||
|
if sys.byteorder == "little":
|
||||||
|
self.failUnless(c_double.__ctype_le__ is c_double)
|
||||||
|
self.failUnless(c_double.__ctype_be__.__ctype_le__ is c_double)
|
||||||
|
else:
|
||||||
|
self.failUnless(c_double.__ctype_be__ is c_double)
|
||||||
|
self.failUnless(c_double.__ctype_le__.__ctype_be__ is c_double)
|
||||||
|
s = c_double(math.pi)
|
||||||
|
self.failUnlessEqual(s.value, math.pi)
|
||||||
|
self.failUnlessEqual(bin(struct.pack("d", math.pi)), bin(s))
|
||||||
|
s = c_double.__ctype_le__(math.pi)
|
||||||
|
self.failUnlessEqual(s.value, math.pi)
|
||||||
|
self.failUnlessEqual(bin(struct.pack("<d", math.pi)), bin(s))
|
||||||
|
s = c_double.__ctype_be__(math.pi)
|
||||||
|
self.failUnlessEqual(s.value, math.pi)
|
||||||
|
self.failUnlessEqual(bin(struct.pack(">d", math.pi)), bin(s))
|
||||||
|
|
||||||
|
def test_endian_other(self):
|
||||||
|
self.failUnless(c_byte.__ctype_le__ is c_byte)
|
||||||
|
self.failUnless(c_byte.__ctype_be__ is c_byte)
|
||||||
|
|
||||||
|
self.failUnless(c_ubyte.__ctype_le__ is c_ubyte)
|
||||||
|
self.failUnless(c_ubyte.__ctype_be__ is c_ubyte)
|
||||||
|
|
||||||
|
self.failUnless(c_char.__ctype_le__ is c_char)
|
||||||
|
self.failUnless(c_char.__ctype_be__ is c_char)
|
||||||
|
|
||||||
|
def test_struct_fields(self):
|
||||||
|
if sys.byteorder == "little":
|
||||||
|
base = BigEndianStructure
|
||||||
|
else:
|
||||||
|
base = LittleEndianStructure
|
||||||
|
|
||||||
|
class T(base):
|
||||||
|
pass
|
||||||
|
_fields_ = [("a", c_ubyte),
|
||||||
|
("b", c_byte),
|
||||||
|
("c", c_short),
|
||||||
|
("d", c_ushort),
|
||||||
|
("e", c_int),
|
||||||
|
("f", c_uint),
|
||||||
|
("g", c_long),
|
||||||
|
("h", c_ulong),
|
||||||
|
("i", c_longlong),
|
||||||
|
("k", c_ulonglong),
|
||||||
|
("l", c_float),
|
||||||
|
("m", c_double),
|
||||||
|
("n", c_char),
|
||||||
|
|
||||||
|
("b1", c_byte, 3),
|
||||||
|
("b2", c_byte, 3),
|
||||||
|
("b3", c_byte, 2),
|
||||||
|
("a", c_int * 3 * 3 * 3)]
|
||||||
|
T._fields_ = _fields_
|
||||||
|
|
||||||
|
# these fields do not support different byte order:
|
||||||
|
for typ in c_wchar, c_void_p, POINTER(c_int):
|
||||||
|
_fields_.append(("x", typ))
|
||||||
|
class T(base):
|
||||||
|
pass
|
||||||
|
self.assertRaises(TypeError, setattr, T, "_fields_", [("x", typ)])
|
||||||
|
|
||||||
|
def test_struct_struct(self):
|
||||||
|
# Nested structures with different byte order not (yet) supported
|
||||||
|
if sys.byteorder == "little":
|
||||||
|
base = BigEndianStructure
|
||||||
|
else:
|
||||||
|
base = LittleEndianStructure
|
||||||
|
|
||||||
|
class T(Structure):
|
||||||
|
_fields_ = [("a", c_int),
|
||||||
|
("b", c_int)]
|
||||||
|
class S(base):
|
||||||
|
pass
|
||||||
|
self.assertRaises(TypeError, setattr, S, "_fields_", [("s", T)])
|
||||||
|
|
||||||
|
def test_struct_fields(self):
|
||||||
|
if sys.byteorder == "little":
|
||||||
|
base = BigEndianStructure
|
||||||
|
fmt = ">bhid"
|
||||||
|
else:
|
||||||
|
base = LittleEndianStructure
|
||||||
|
fmt = "<bhid"
|
||||||
|
|
||||||
|
class S(base):
|
||||||
|
_pack_ = 1 # struct with '<' or '>' uses standard alignment.
|
||||||
|
_fields_ = [("b", c_byte),
|
||||||
|
("h", c_short),
|
||||||
|
("i", c_int),
|
||||||
|
("d", c_double)]
|
||||||
|
|
||||||
|
s1 = S(0x12, 0x1234, 0x12345678, 3.14)
|
||||||
|
s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
|
||||||
|
self.failUnlessEqual(bin(s1), bin(s2))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
139
Lib/ctypes/test/test_callbacks.py
Normal file
139
Lib/ctypes/test/test_callbacks.py
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
import _ctypes_test
|
||||||
|
|
||||||
|
class Callbacks(unittest.TestCase):
|
||||||
|
functype = CFUNCTYPE
|
||||||
|
|
||||||
|
## def tearDown(self):
|
||||||
|
## import gc
|
||||||
|
## gc.collect()
|
||||||
|
|
||||||
|
def callback(self, *args):
|
||||||
|
self.got_args = args
|
||||||
|
return args[-1]
|
||||||
|
|
||||||
|
def check_type(self, typ, arg):
|
||||||
|
PROTO = self.functype.im_func(typ, typ)
|
||||||
|
result = PROTO(self.callback)(arg)
|
||||||
|
if typ == c_float:
|
||||||
|
self.failUnlessAlmostEqual(result, arg, places=5)
|
||||||
|
else:
|
||||||
|
self.failUnlessEqual(self.got_args, (arg,))
|
||||||
|
self.failUnlessEqual(result, arg)
|
||||||
|
|
||||||
|
PROTO = self.functype.im_func(typ, c_byte, typ)
|
||||||
|
result = PROTO(self.callback)(-3, arg)
|
||||||
|
if typ == c_float:
|
||||||
|
self.failUnlessAlmostEqual(result, arg, places=5)
|
||||||
|
else:
|
||||||
|
self.failUnlessEqual(self.got_args, (-3, arg))
|
||||||
|
self.failUnlessEqual(result, arg)
|
||||||
|
|
||||||
|
################
|
||||||
|
|
||||||
|
def test_byte(self):
|
||||||
|
self.check_type(c_byte, 42)
|
||||||
|
self.check_type(c_byte, -42)
|
||||||
|
|
||||||
|
def test_ubyte(self):
|
||||||
|
self.check_type(c_ubyte, 42)
|
||||||
|
|
||||||
|
def test_short(self):
|
||||||
|
self.check_type(c_short, 42)
|
||||||
|
self.check_type(c_short, -42)
|
||||||
|
|
||||||
|
def test_ushort(self):
|
||||||
|
self.check_type(c_ushort, 42)
|
||||||
|
|
||||||
|
def test_int(self):
|
||||||
|
self.check_type(c_int, 42)
|
||||||
|
self.check_type(c_int, -42)
|
||||||
|
|
||||||
|
def test_uint(self):
|
||||||
|
self.check_type(c_uint, 42)
|
||||||
|
|
||||||
|
def test_long(self):
|
||||||
|
self.check_type(c_long, 42)
|
||||||
|
self.check_type(c_long, -42)
|
||||||
|
|
||||||
|
def test_ulong(self):
|
||||||
|
self.check_type(c_ulong, 42)
|
||||||
|
|
||||||
|
def test_longlong(self):
|
||||||
|
self.check_type(c_longlong, 42)
|
||||||
|
self.check_type(c_longlong, -42)
|
||||||
|
|
||||||
|
def test_ulonglong(self):
|
||||||
|
self.check_type(c_ulonglong, 42)
|
||||||
|
|
||||||
|
def test_float(self):
|
||||||
|
# only almost equal: double -> float -> double
|
||||||
|
import math
|
||||||
|
self.check_type(c_float, math.e)
|
||||||
|
self.check_type(c_float, -math.e)
|
||||||
|
|
||||||
|
def test_double(self):
|
||||||
|
self.check_type(c_double, 3.14)
|
||||||
|
self.check_type(c_double, -3.14)
|
||||||
|
|
||||||
|
def test_char(self):
|
||||||
|
self.check_type(c_char, "x")
|
||||||
|
self.check_type(c_char, "a")
|
||||||
|
|
||||||
|
# disabled: would now (correctly) raise a RuntimeWarning about
|
||||||
|
# a memory leak. A callback function cannot return a non-integral
|
||||||
|
# C type without causing a memory leak.
|
||||||
|
## def test_char_p(self):
|
||||||
|
## self.check_type(c_char_p, "abc")
|
||||||
|
## self.check_type(c_char_p, "def")
|
||||||
|
|
||||||
|
def test_pyobject(self):
|
||||||
|
o = ()
|
||||||
|
from sys import getrefcount as grc
|
||||||
|
for o in (), [], object():
|
||||||
|
initial = grc(o)
|
||||||
|
# This call leaks a reference to 'o'...
|
||||||
|
self.check_type(py_object, o)
|
||||||
|
before = grc(o)
|
||||||
|
# ...but this call doesn't leak any more. Where is the refcount?
|
||||||
|
self.check_type(py_object, o)
|
||||||
|
after = grc(o)
|
||||||
|
self.failUnlessEqual((after, o), (before, o))
|
||||||
|
|
||||||
|
try:
|
||||||
|
WINFUNCTYPE
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
class StdcallCallbacks(Callbacks):
|
||||||
|
functype = WINFUNCTYPE
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
class SampleCallbacksTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_integrate(self):
|
||||||
|
# Derived from some then non-working code, posted by David Foster
|
||||||
|
dll = cdll.load(_ctypes_test.__file__)
|
||||||
|
|
||||||
|
# The function prototype called by 'integrate': double func(double);
|
||||||
|
CALLBACK = CFUNCTYPE(c_double, c_double)
|
||||||
|
|
||||||
|
# The integrate function itself, exposed from the _ctypes_test dll
|
||||||
|
integrate = dll.integrate
|
||||||
|
integrate.argtypes = (c_double, c_double, CALLBACK, c_long)
|
||||||
|
integrate.restype = c_double
|
||||||
|
|
||||||
|
def func(x):
|
||||||
|
return x**2
|
||||||
|
|
||||||
|
result = integrate(0.0, 1.0, CALLBACK(func), 10)
|
||||||
|
diff = abs(result - 1./3.)
|
||||||
|
|
||||||
|
self.failUnless(diff < 0.01, "%s not less than 0.01" % diff)
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
55
Lib/ctypes/test/test_cast.py
Normal file
55
Lib/ctypes/test/test_cast.py
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
from ctypes import *
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
|
||||||
|
class Test(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_array2pointer(self):
|
||||||
|
array = (c_int * 3)(42, 17, 2)
|
||||||
|
|
||||||
|
# casting an array to a pointer works.
|
||||||
|
ptr = cast(array, POINTER(c_int))
|
||||||
|
self.failUnlessEqual([ptr[i] for i in range(3)], [42, 17, 2])
|
||||||
|
|
||||||
|
if 2*sizeof(c_short) == sizeof(c_int):
|
||||||
|
ptr = cast(array, POINTER(c_short))
|
||||||
|
if sys.byteorder == "little":
|
||||||
|
self.failUnlessEqual([ptr[i] for i in range(6)],
|
||||||
|
[42, 0, 17, 0, 2, 0])
|
||||||
|
else:
|
||||||
|
self.failUnlessEqual([ptr[i] for i in range(6)],
|
||||||
|
[0, 42, 0, 17, 0, 2])
|
||||||
|
|
||||||
|
def test_address2pointer(self):
|
||||||
|
array = (c_int * 3)(42, 17, 2)
|
||||||
|
|
||||||
|
# on AMD64, sizeof(int) == 4 and sizeof(void *) == 8.
|
||||||
|
# By default, cast would convert a Python int (or long) into
|
||||||
|
# a C int, which would be too short to represent a pointer
|
||||||
|
# on this platform.
|
||||||
|
|
||||||
|
# So we have to wrap the address into a c_void_p for this to work.
|
||||||
|
#
|
||||||
|
# XXX Better would be to hide the differences in the cast function.
|
||||||
|
address = addressof(array)
|
||||||
|
ptr = cast(c_void_p(address), POINTER(c_int))
|
||||||
|
self.failUnlessEqual([ptr[i] for i in range(3)], [42, 17, 2])
|
||||||
|
|
||||||
|
|
||||||
|
def test_ptr2array(self):
|
||||||
|
array = (c_int * 3)(42, 17, 2)
|
||||||
|
|
||||||
|
## # Hm, already tested above.
|
||||||
|
## ptr = cast(array, POINTER(c_int))
|
||||||
|
## self.failUnlessEqual([ptr[i] for i in range(3)], [42, 17, 2])
|
||||||
|
|
||||||
|
# print cast(addressof(array), c_int * 3)[:]
|
||||||
|
## ptr = cast(addressof(ptr)
|
||||||
|
|
||||||
|
## print ptr[0], ptr[1], ptr[2]
|
||||||
|
## ptr = POINTER(c_int).from_address(addressof(array))
|
||||||
|
## # XXX this crashes:
|
||||||
|
## print ptr[0], ptr[1], ptr[2]
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
191
Lib/ctypes/test/test_cfuncs.py
Normal file
191
Lib/ctypes/test/test_cfuncs.py
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
# A lot of failures in these tests on Mac OS X.
|
||||||
|
# Byte order related?
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
import _ctypes_test
|
||||||
|
|
||||||
|
class CFunctions(unittest.TestCase):
|
||||||
|
_dll = cdll.load(_ctypes_test.__file__)
|
||||||
|
|
||||||
|
def S(self):
|
||||||
|
return c_longlong.in_dll(self._dll, "last_tf_arg_s").value
|
||||||
|
def U(self):
|
||||||
|
return c_ulonglong.in_dll(self._dll, "last_tf_arg_u").value
|
||||||
|
|
||||||
|
def test_byte(self):
|
||||||
|
self._dll.tf_b.restype = c_byte
|
||||||
|
self._dll.tf_b.argtypes = (c_byte,)
|
||||||
|
self.failUnlessEqual(self._dll.tf_b(-126), -42)
|
||||||
|
self.failUnlessEqual(self.S(), -126)
|
||||||
|
|
||||||
|
def test_byte_plus(self):
|
||||||
|
self._dll.tf_bb.restype = c_byte
|
||||||
|
self._dll.tf_bb.argtypes = (c_byte, c_byte)
|
||||||
|
self.failUnlessEqual(self._dll.tf_bb(0, -126), -42)
|
||||||
|
self.failUnlessEqual(self.S(), -126)
|
||||||
|
|
||||||
|
def test_ubyte(self):
|
||||||
|
self._dll.tf_B.restype = c_ubyte
|
||||||
|
self._dll.tf_B.argtypes = (c_ubyte,)
|
||||||
|
self.failUnlessEqual(self._dll.tf_B(255), 85)
|
||||||
|
self.failUnlessEqual(self.U(), 255)
|
||||||
|
|
||||||
|
def test_ubyte_plus(self):
|
||||||
|
self._dll.tf_bB.restype = c_ubyte
|
||||||
|
self._dll.tf_bB.argtypes = (c_byte, c_ubyte)
|
||||||
|
self.failUnlessEqual(self._dll.tf_bB(0, 255), 85)
|
||||||
|
self.failUnlessEqual(self.U(), 255)
|
||||||
|
|
||||||
|
def test_short(self):
|
||||||
|
self._dll.tf_h.restype = c_short
|
||||||
|
self.failUnlessEqual(self._dll.tf_h(-32766), -10922)
|
||||||
|
self.failUnlessEqual(self.S(), -32766)
|
||||||
|
|
||||||
|
def test_short_plus(self):
|
||||||
|
self._dll.tf_bh.restype = c_short
|
||||||
|
self.failUnlessEqual(self._dll.tf_bh(0, -32766), -10922)
|
||||||
|
self.failUnlessEqual(self.S(), -32766)
|
||||||
|
|
||||||
|
def test_ushort(self):
|
||||||
|
self._dll.tf_H.restype = c_ushort
|
||||||
|
self.failUnlessEqual(self._dll.tf_H(65535), 21845)
|
||||||
|
self.failUnlessEqual(self.U(), 65535)
|
||||||
|
|
||||||
|
def test_ushort_plus(self):
|
||||||
|
self._dll.tf_bH.restype = c_ushort
|
||||||
|
self.failUnlessEqual(self._dll.tf_bH(0, 65535), 21845)
|
||||||
|
self.failUnlessEqual(self.U(), 65535)
|
||||||
|
|
||||||
|
def test_int(self):
|
||||||
|
self._dll.tf_i.restype = c_int
|
||||||
|
self.failUnlessEqual(self._dll.tf_i(-2147483646), -715827882)
|
||||||
|
self.failUnlessEqual(self.S(), -2147483646)
|
||||||
|
|
||||||
|
def test_int_plus(self):
|
||||||
|
self._dll.tf_bi.restype = c_int
|
||||||
|
self.failUnlessEqual(self._dll.tf_bi(0, -2147483646), -715827882)
|
||||||
|
self.failUnlessEqual(self.S(), -2147483646)
|
||||||
|
|
||||||
|
def test_uint(self):
|
||||||
|
self._dll.tf_I.restype = c_uint
|
||||||
|
self.failUnlessEqual(self._dll.tf_I(4294967295), 1431655765)
|
||||||
|
self.failUnlessEqual(self.U(), 4294967295)
|
||||||
|
|
||||||
|
def test_uint_plus(self):
|
||||||
|
self._dll.tf_bI.restype = c_uint
|
||||||
|
self.failUnlessEqual(self._dll.tf_bI(0, 4294967295), 1431655765)
|
||||||
|
self.failUnlessEqual(self.U(), 4294967295)
|
||||||
|
|
||||||
|
def test_long(self):
|
||||||
|
self._dll.tf_l.restype = c_long
|
||||||
|
self._dll.tf_l.argtypes = (c_long,)
|
||||||
|
self.failUnlessEqual(self._dll.tf_l(-2147483646), -715827882)
|
||||||
|
self.failUnlessEqual(self.S(), -2147483646)
|
||||||
|
|
||||||
|
def test_long_plus(self):
|
||||||
|
self._dll.tf_bl.restype = c_long
|
||||||
|
self._dll.tf_bl.argtypes = (c_byte, c_long)
|
||||||
|
self.failUnlessEqual(self._dll.tf_bl(0, -2147483646), -715827882)
|
||||||
|
self.failUnlessEqual(self.S(), -2147483646)
|
||||||
|
|
||||||
|
def test_ulong(self):
|
||||||
|
self._dll.tf_L.restype = c_ulong
|
||||||
|
self._dll.tf_L.argtypes = (c_ulong,)
|
||||||
|
self.failUnlessEqual(self._dll.tf_L(4294967295), 1431655765)
|
||||||
|
self.failUnlessEqual(self.U(), 4294967295)
|
||||||
|
|
||||||
|
def test_ulong_plus(self):
|
||||||
|
self._dll.tf_bL.restype = c_ulong
|
||||||
|
self._dll.tf_bL.argtypes = (c_char, c_ulong)
|
||||||
|
self.failUnlessEqual(self._dll.tf_bL(' ', 4294967295), 1431655765)
|
||||||
|
self.failUnlessEqual(self.U(), 4294967295)
|
||||||
|
|
||||||
|
def test_longlong(self):
|
||||||
|
self._dll.tf_q.restype = c_longlong
|
||||||
|
self._dll.tf_q.argtypes = (c_longlong, )
|
||||||
|
self.failUnlessEqual(self._dll.tf_q(-9223372036854775806), -3074457345618258602)
|
||||||
|
self.failUnlessEqual(self.S(), -9223372036854775806)
|
||||||
|
|
||||||
|
def test_longlong_plus(self):
|
||||||
|
self._dll.tf_bq.restype = c_longlong
|
||||||
|
self._dll.tf_bq.argtypes = (c_byte, c_longlong)
|
||||||
|
self.failUnlessEqual(self._dll.tf_bq(0, -9223372036854775806), -3074457345618258602)
|
||||||
|
self.failUnlessEqual(self.S(), -9223372036854775806)
|
||||||
|
|
||||||
|
def test_ulonglong(self):
|
||||||
|
self._dll.tf_Q.restype = c_ulonglong
|
||||||
|
self._dll.tf_Q.argtypes = (c_ulonglong, )
|
||||||
|
self.failUnlessEqual(self._dll.tf_Q(18446744073709551615), 6148914691236517205)
|
||||||
|
self.failUnlessEqual(self.U(), 18446744073709551615)
|
||||||
|
|
||||||
|
def test_ulonglong_plus(self):
|
||||||
|
self._dll.tf_bQ.restype = c_ulonglong
|
||||||
|
self._dll.tf_bQ.argtypes = (c_byte, c_ulonglong)
|
||||||
|
self.failUnlessEqual(self._dll.tf_bQ(0, 18446744073709551615), 6148914691236517205)
|
||||||
|
self.failUnlessEqual(self.U(), 18446744073709551615)
|
||||||
|
|
||||||
|
def test_float(self):
|
||||||
|
self._dll.tf_f.restype = c_float
|
||||||
|
self._dll.tf_f.argtypes = (c_float,)
|
||||||
|
self.failUnlessEqual(self._dll.tf_f(-42.), -14.)
|
||||||
|
self.failUnlessEqual(self.S(), -42)
|
||||||
|
|
||||||
|
def test_float_plus(self):
|
||||||
|
self._dll.tf_bf.restype = c_float
|
||||||
|
self._dll.tf_bf.argtypes = (c_byte, c_float)
|
||||||
|
self.failUnlessEqual(self._dll.tf_bf(0, -42.), -14.)
|
||||||
|
self.failUnlessEqual(self.S(), -42)
|
||||||
|
|
||||||
|
def test_double(self):
|
||||||
|
self._dll.tf_d.restype = c_double
|
||||||
|
self._dll.tf_d.argtypes = (c_double,)
|
||||||
|
self.failUnlessEqual(self._dll.tf_d(42.), 14.)
|
||||||
|
self.failUnlessEqual(self.S(), 42)
|
||||||
|
|
||||||
|
def test_double_plus(self):
|
||||||
|
self._dll.tf_bd.restype = c_double
|
||||||
|
self._dll.tf_bd.argtypes = (c_byte, c_double)
|
||||||
|
self.failUnlessEqual(self._dll.tf_bd(0, 42.), 14.)
|
||||||
|
self.failUnlessEqual(self.S(), 42)
|
||||||
|
|
||||||
|
def test_callwithresult(self):
|
||||||
|
def process_result(result):
|
||||||
|
return result * 2
|
||||||
|
self._dll.tf_i.restype = process_result
|
||||||
|
self._dll.tf_i.argtypes = (c_int,)
|
||||||
|
self.failUnlessEqual(self._dll.tf_i(42), 28)
|
||||||
|
self.failUnlessEqual(self.S(), 42)
|
||||||
|
self.failUnlessEqual(self._dll.tf_i(-42), -28)
|
||||||
|
self.failUnlessEqual(self.S(), -42)
|
||||||
|
|
||||||
|
def test_void(self):
|
||||||
|
self._dll.tv_i.restype = None
|
||||||
|
self._dll.tv_i.argtypes = (c_int,)
|
||||||
|
self.failUnlessEqual(self._dll.tv_i(42), None)
|
||||||
|
self.failUnlessEqual(self.S(), 42)
|
||||||
|
self.failUnlessEqual(self._dll.tv_i(-42), None)
|
||||||
|
self.failUnlessEqual(self.S(), -42)
|
||||||
|
|
||||||
|
# The following repeates the above tests with stdcall functions (where
|
||||||
|
# they are available)
|
||||||
|
try:
|
||||||
|
WinDLL
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
class stdcall_dll(WinDLL):
|
||||||
|
def __getattr__(self, name):
|
||||||
|
if name[:2] == '__' and name[-2:] == '__':
|
||||||
|
raise AttributeError, name
|
||||||
|
func = self._FuncPtr("s_" + name, self)
|
||||||
|
setattr(self, name, func)
|
||||||
|
return func
|
||||||
|
|
||||||
|
class stdcallCFunctions(CFunctions):
|
||||||
|
_dll = stdcall_dll(_ctypes_test.__file__)
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
40
Lib/ctypes/test/test_checkretval.py
Normal file
40
Lib/ctypes/test/test_checkretval.py
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
class Test(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_checkretval(self):
|
||||||
|
|
||||||
|
class CHECKED(c_int):
|
||||||
|
def _check_retval_(value):
|
||||||
|
# Receives a CHECKED instance.
|
||||||
|
return str(value.value)
|
||||||
|
_check_retval_ = staticmethod(_check_retval_)
|
||||||
|
|
||||||
|
import _ctypes_test
|
||||||
|
dll = cdll.load(_ctypes_test.__file__)
|
||||||
|
self.failUnlessEqual(42, dll._testfunc_p_p(42))
|
||||||
|
|
||||||
|
dll._testfunc_p_p.restype = CHECKED
|
||||||
|
self.failUnlessEqual("42", dll._testfunc_p_p(42))
|
||||||
|
|
||||||
|
dll._testfunc_p_p.restype = None
|
||||||
|
self.failUnlessEqual(None, dll._testfunc_p_p(42))
|
||||||
|
|
||||||
|
del dll._testfunc_p_p.restype
|
||||||
|
self.failUnlessEqual(42, dll._testfunc_p_p(42))
|
||||||
|
|
||||||
|
try:
|
||||||
|
oledll
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
def test_oledll(self):
|
||||||
|
self.failUnlessRaises(WindowsError,
|
||||||
|
oledll.oleaut32.CreateTypeLib2,
|
||||||
|
0, 0, 0)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
19
Lib/ctypes/test/test_errcheck.py
Normal file
19
Lib/ctypes/test/test_errcheck.py
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import sys
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
##class HMODULE(Structure):
|
||||||
|
## _fields_ = [("value", c_void_p)]
|
||||||
|
|
||||||
|
## def __repr__(self):
|
||||||
|
## return "<HMODULE %s>" % self.value
|
||||||
|
|
||||||
|
##windll.kernel32.GetModuleHandleA.restype = HMODULE
|
||||||
|
|
||||||
|
##print windll.kernel32.GetModuleHandleA("python23.dll")
|
||||||
|
##print hex(sys.dllhandle)
|
||||||
|
|
||||||
|
##def nonzero(handle):
|
||||||
|
## return (GetLastError(), handle)
|
||||||
|
|
||||||
|
##windll.kernel32.GetModuleHandleA.errcheck = nonzero
|
||||||
|
##print windll.kernel32.GetModuleHandleA("spam")
|
||||||
127
Lib/ctypes/test/test_funcptr.py
Normal file
127
Lib/ctypes/test/test_funcptr.py
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
import os, unittest
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
try:
|
||||||
|
WINFUNCTYPE
|
||||||
|
except NameError:
|
||||||
|
# fake to enable this test on Linux
|
||||||
|
WINFUNCTYPE = CFUNCTYPE
|
||||||
|
|
||||||
|
import _ctypes_test
|
||||||
|
lib = cdll.load(_ctypes_test.__file__)
|
||||||
|
|
||||||
|
class CFuncPtrTestCase(unittest.TestCase):
|
||||||
|
def test_basic(self):
|
||||||
|
X = WINFUNCTYPE(c_int, c_int, c_int)
|
||||||
|
|
||||||
|
def func(*args):
|
||||||
|
return len(args)
|
||||||
|
|
||||||
|
x = X(func)
|
||||||
|
self.failUnlessEqual(x.restype, c_int)
|
||||||
|
self.failUnlessEqual(x.argtypes, (c_int, c_int))
|
||||||
|
self.failUnlessEqual(sizeof(x), sizeof(c_voidp))
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_voidp))
|
||||||
|
|
||||||
|
def test_first(self):
|
||||||
|
StdCallback = WINFUNCTYPE(c_int, c_int, c_int)
|
||||||
|
CdeclCallback = CFUNCTYPE(c_int, c_int, c_int)
|
||||||
|
|
||||||
|
def func(a, b):
|
||||||
|
return a + b
|
||||||
|
|
||||||
|
s = StdCallback(func)
|
||||||
|
c = CdeclCallback(func)
|
||||||
|
|
||||||
|
self.failUnlessEqual(s(1, 2), 3)
|
||||||
|
self.failUnlessEqual(c(1, 2), 3)
|
||||||
|
# The following no longer raises a TypeError - it is now
|
||||||
|
# possible, as in C, to call cdecl functions with more parameters.
|
||||||
|
#self.assertRaises(TypeError, c, 1, 2, 3)
|
||||||
|
self.failUnlessEqual(c(1, 2, 3, 4, 5, 6), 3)
|
||||||
|
if not WINFUNCTYPE is CFUNCTYPE and os.name != "ce":
|
||||||
|
self.assertRaises(TypeError, s, 1, 2, 3)
|
||||||
|
|
||||||
|
def test_structures(self):
|
||||||
|
WNDPROC = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int)
|
||||||
|
|
||||||
|
def wndproc(hwnd, msg, wParam, lParam):
|
||||||
|
return hwnd + msg + wParam + lParam
|
||||||
|
|
||||||
|
HINSTANCE = c_int
|
||||||
|
HICON = c_int
|
||||||
|
HCURSOR = c_int
|
||||||
|
LPCTSTR = c_char_p
|
||||||
|
|
||||||
|
class WNDCLASS(Structure):
|
||||||
|
_fields_ = [("style", c_uint),
|
||||||
|
("lpfnWndProc", WNDPROC),
|
||||||
|
("cbClsExtra", c_int),
|
||||||
|
("cbWndExtra", c_int),
|
||||||
|
("hInstance", HINSTANCE),
|
||||||
|
("hIcon", HICON),
|
||||||
|
("hCursor", HCURSOR),
|
||||||
|
("lpszMenuName", LPCTSTR),
|
||||||
|
("lpszClassName", LPCTSTR)]
|
||||||
|
|
||||||
|
wndclass = WNDCLASS()
|
||||||
|
wndclass.lpfnWndProc = WNDPROC(wndproc)
|
||||||
|
|
||||||
|
WNDPROC_2 = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int)
|
||||||
|
|
||||||
|
# This is no longer true, now that WINFUNCTYPE caches created types internally.
|
||||||
|
## # CFuncPtr subclasses are compared by identity, so this raises a TypeError:
|
||||||
|
## self.assertRaises(TypeError, setattr, wndclass,
|
||||||
|
## "lpfnWndProc", WNDPROC_2(wndproc))
|
||||||
|
# instead:
|
||||||
|
|
||||||
|
self.failUnless(WNDPROC is WNDPROC_2)
|
||||||
|
# 'wndclass.lpfnWndProc' leaks 94 references. Why?
|
||||||
|
self.failUnlessEqual(wndclass.lpfnWndProc(1, 2, 3, 4), 10)
|
||||||
|
|
||||||
|
|
||||||
|
f = wndclass.lpfnWndProc
|
||||||
|
|
||||||
|
del wndclass
|
||||||
|
del wndproc
|
||||||
|
|
||||||
|
self.failUnlessEqual(f(10, 11, 12, 13), 46)
|
||||||
|
|
||||||
|
def test_dllfunctions(self):
|
||||||
|
|
||||||
|
def NoNullHandle(value):
|
||||||
|
if not value:
|
||||||
|
raise WinError()
|
||||||
|
return value
|
||||||
|
|
||||||
|
strchr = lib.my_strchr
|
||||||
|
strchr.restype = c_char_p
|
||||||
|
strchr.argtypes = (c_char_p, c_char)
|
||||||
|
self.failUnlessEqual(strchr("abcdefghi", "b"), "bcdefghi")
|
||||||
|
self.failUnlessEqual(strchr("abcdefghi", "x"), None)
|
||||||
|
|
||||||
|
|
||||||
|
strtok = lib.my_strtok
|
||||||
|
strtok.restype = c_char_p
|
||||||
|
# Neither of this does work: strtok changes the buffer it is passed
|
||||||
|
## strtok.argtypes = (c_char_p, c_char_p)
|
||||||
|
## strtok.argtypes = (c_string, c_char_p)
|
||||||
|
|
||||||
|
def c_string(init):
|
||||||
|
size = len(init) + 1
|
||||||
|
return (c_char*size)(*init)
|
||||||
|
|
||||||
|
s = "a\nb\nc"
|
||||||
|
b = c_string(s)
|
||||||
|
|
||||||
|
## b = (c_char * (len(s)+1))()
|
||||||
|
## b.value = s
|
||||||
|
|
||||||
|
## b = c_string(s)
|
||||||
|
self.failUnlessEqual(strtok(b, "\n"), "a")
|
||||||
|
self.failUnlessEqual(strtok(None, "\n"), "b")
|
||||||
|
self.failUnlessEqual(strtok(None, "\n"), "c")
|
||||||
|
self.failUnlessEqual(strtok(None, "\n"), None)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
381
Lib/ctypes/test/test_functions.py
Normal file
381
Lib/ctypes/test/test_functions.py
Normal file
|
|
@ -0,0 +1,381 @@
|
||||||
|
"""
|
||||||
|
Here is probably the place to write the docs, since the test-cases
|
||||||
|
show how the type behave.
|
||||||
|
|
||||||
|
Later...
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ctypes import *
|
||||||
|
import sys, unittest
|
||||||
|
|
||||||
|
try:
|
||||||
|
WINFUNCTYPE
|
||||||
|
except NameError:
|
||||||
|
# fake to enable this test on Linux
|
||||||
|
WINFUNCTYPE = CFUNCTYPE
|
||||||
|
|
||||||
|
import _ctypes_test
|
||||||
|
dll = cdll.load(_ctypes_test.__file__)
|
||||||
|
if sys.platform == "win32":
|
||||||
|
windll = windll.load(_ctypes_test.__file__)
|
||||||
|
|
||||||
|
class FunctionTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_mro(self):
|
||||||
|
# in Python 2.3, this raises TypeError: MRO conflict among bases classes,
|
||||||
|
# in Python 2.2 it works.
|
||||||
|
#
|
||||||
|
# But in early versions of _ctypes.c, the result of tp_new
|
||||||
|
# wasn't checked, and it even crashed Python.
|
||||||
|
# Found by Greg Chapman.
|
||||||
|
|
||||||
|
try:
|
||||||
|
class X(object, Array):
|
||||||
|
_length_ = 5
|
||||||
|
_type_ = "i"
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
from _ctypes import _Pointer
|
||||||
|
try:
|
||||||
|
class X(object, _Pointer):
|
||||||
|
pass
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
from _ctypes import _SimpleCData
|
||||||
|
try:
|
||||||
|
class X(object, _SimpleCData):
|
||||||
|
_type_ = "i"
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
class X(object, Structure):
|
||||||
|
_fields_ = []
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_wchar_parm(self):
|
||||||
|
try:
|
||||||
|
c_wchar
|
||||||
|
except NameError:
|
||||||
|
return
|
||||||
|
f = dll._testfunc_i_bhilfd
|
||||||
|
f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double]
|
||||||
|
result = f(1, u"x", 3, 4, 5.0, 6.0)
|
||||||
|
self.failUnlessEqual(result, 139)
|
||||||
|
self.failUnlessEqual(type(result), int)
|
||||||
|
|
||||||
|
def test_wchar_result(self):
|
||||||
|
try:
|
||||||
|
c_wchar
|
||||||
|
except NameError:
|
||||||
|
return
|
||||||
|
f = dll._testfunc_i_bhilfd
|
||||||
|
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
|
||||||
|
f.restype = c_wchar
|
||||||
|
result = f(0, 0, 0, 0, 0, 0)
|
||||||
|
self.failUnlessEqual(result, u'\x00')
|
||||||
|
|
||||||
|
def test_voidresult(self):
|
||||||
|
f = dll._testfunc_v
|
||||||
|
f.restype = None
|
||||||
|
f.argtypes = [c_int, c_int, POINTER(c_int)]
|
||||||
|
result = c_int()
|
||||||
|
self.failUnlessEqual(None, f(1, 2, byref(result)))
|
||||||
|
self.failUnlessEqual(result.value, 3)
|
||||||
|
|
||||||
|
def test_intresult(self):
|
||||||
|
f = dll._testfunc_i_bhilfd
|
||||||
|
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
|
||||||
|
result = f(1, 2, 3, 4, 5.0, 6.0)
|
||||||
|
self.failUnlessEqual(result, 21)
|
||||||
|
self.failUnlessEqual(type(result), int)
|
||||||
|
|
||||||
|
result = f(-1, -2, -3, -4, -5.0, -6.0)
|
||||||
|
self.failUnlessEqual(result, -21)
|
||||||
|
self.failUnlessEqual(type(result), int)
|
||||||
|
|
||||||
|
# If we declare the function to return a short,
|
||||||
|
# is the high part split off?
|
||||||
|
f.restype = c_short
|
||||||
|
result = f(1, 2, 3, 4, 5.0, 6.0)
|
||||||
|
self.failUnlessEqual(result, 21)
|
||||||
|
self.failUnlessEqual(type(result), int)
|
||||||
|
|
||||||
|
result = f(1, 2, 3, 0x10004, 5.0, 6.0)
|
||||||
|
self.failUnlessEqual(result, 21)
|
||||||
|
self.failUnlessEqual(type(result), int)
|
||||||
|
|
||||||
|
# You cannot assing character format codes as restype any longer
|
||||||
|
self.assertRaises(TypeError, setattr, f, "restype", "i")
|
||||||
|
|
||||||
|
def test_floatresult(self):
|
||||||
|
f = dll._testfunc_f_bhilfd
|
||||||
|
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
|
||||||
|
f.restype = c_float
|
||||||
|
result = f(1, 2, 3, 4, 5.0, 6.0)
|
||||||
|
self.failUnlessEqual(result, 21)
|
||||||
|
self.failUnlessEqual(type(result), float)
|
||||||
|
|
||||||
|
result = f(-1, -2, -3, -4, -5.0, -6.0)
|
||||||
|
self.failUnlessEqual(result, -21)
|
||||||
|
self.failUnlessEqual(type(result), float)
|
||||||
|
|
||||||
|
def test_doubleresult(self):
|
||||||
|
f = dll._testfunc_d_bhilfd
|
||||||
|
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
|
||||||
|
f.restype = c_double
|
||||||
|
result = f(1, 2, 3, 4, 5.0, 6.0)
|
||||||
|
self.failUnlessEqual(result, 21)
|
||||||
|
self.failUnlessEqual(type(result), float)
|
||||||
|
|
||||||
|
result = f(-1, -2, -3, -4, -5.0, -6.0)
|
||||||
|
self.failUnlessEqual(result, -21)
|
||||||
|
self.failUnlessEqual(type(result), float)
|
||||||
|
|
||||||
|
def test_longlongresult(self):
|
||||||
|
try:
|
||||||
|
c_longlong
|
||||||
|
except NameError:
|
||||||
|
return
|
||||||
|
f = dll._testfunc_q_bhilfd
|
||||||
|
f.restype = c_longlong
|
||||||
|
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
|
||||||
|
result = f(1, 2, 3, 4, 5.0, 6.0)
|
||||||
|
self.failUnlessEqual(result, 21)
|
||||||
|
|
||||||
|
f = dll._testfunc_q_bhilfdq
|
||||||
|
f.restype = c_longlong
|
||||||
|
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double, c_longlong]
|
||||||
|
result = f(1, 2, 3, 4, 5.0, 6.0, 21)
|
||||||
|
self.failUnlessEqual(result, 42)
|
||||||
|
|
||||||
|
def test_stringresult(self):
|
||||||
|
f = dll._testfunc_p_p
|
||||||
|
f.argtypes = None
|
||||||
|
f.restype = c_char_p
|
||||||
|
result = f("123")
|
||||||
|
self.failUnlessEqual(result, "123")
|
||||||
|
|
||||||
|
result = f(None)
|
||||||
|
self.failUnlessEqual(result, None)
|
||||||
|
|
||||||
|
def test_pointers(self):
|
||||||
|
f = dll._testfunc_p_p
|
||||||
|
f.restype = POINTER(c_int)
|
||||||
|
f.argtypes = [POINTER(c_int)]
|
||||||
|
|
||||||
|
# This only works if the value c_int(42) passed to the
|
||||||
|
# function is still alive while the pointer (the result) is
|
||||||
|
# used.
|
||||||
|
|
||||||
|
v = c_int(42)
|
||||||
|
|
||||||
|
self.failUnlessEqual(pointer(v).contents.value, 42)
|
||||||
|
result = f(pointer(v))
|
||||||
|
self.failUnlessEqual(type(result), POINTER(c_int))
|
||||||
|
self.failUnlessEqual(result.contents.value, 42)
|
||||||
|
|
||||||
|
# This on works...
|
||||||
|
result = f(pointer(v))
|
||||||
|
self.failUnlessEqual(result.contents.value, v.value)
|
||||||
|
|
||||||
|
p = pointer(c_int(99))
|
||||||
|
result = f(p)
|
||||||
|
self.failUnlessEqual(result.contents.value, 99)
|
||||||
|
|
||||||
|
arg = byref(v)
|
||||||
|
result = f(arg)
|
||||||
|
self.failIfEqual(result.contents, v.value)
|
||||||
|
|
||||||
|
self.assertRaises(ArgumentError, f, byref(c_short(22)))
|
||||||
|
|
||||||
|
# It is dangerous, however, because you don't control the lifetime
|
||||||
|
# of the pointer:
|
||||||
|
result = f(byref(c_int(99)))
|
||||||
|
self.failIfEqual(result.contents, 99)
|
||||||
|
|
||||||
|
def test_errors(self):
|
||||||
|
f = dll._testfunc_p_p
|
||||||
|
f.restype = c_int
|
||||||
|
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("y", c_int)]
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, f, X()) #cannot convert parameter
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
def test_shorts(self):
|
||||||
|
f = dll._testfunc_callback_i_if
|
||||||
|
|
||||||
|
args = []
|
||||||
|
expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048,
|
||||||
|
1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1]
|
||||||
|
|
||||||
|
def callback(v):
|
||||||
|
args.append(v)
|
||||||
|
|
||||||
|
CallBack = CFUNCTYPE(c_int, c_int)
|
||||||
|
|
||||||
|
cb = CallBack(callback)
|
||||||
|
f(2**18, cb)
|
||||||
|
self.failUnlessEqual(args, expected)
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
|
||||||
|
def test_callbacks(self):
|
||||||
|
f = dll._testfunc_callback_i_if
|
||||||
|
f.restype = c_int
|
||||||
|
|
||||||
|
MyCallback = CFUNCTYPE(c_int, c_int)
|
||||||
|
|
||||||
|
def callback(value):
|
||||||
|
#print "called back with", value
|
||||||
|
return value
|
||||||
|
|
||||||
|
cb = MyCallback(callback)
|
||||||
|
result = f(-10, cb)
|
||||||
|
self.failUnlessEqual(result, -18)
|
||||||
|
|
||||||
|
# test with prototype
|
||||||
|
f.argtypes = [c_int, MyCallback]
|
||||||
|
cb = MyCallback(callback)
|
||||||
|
result = f(-10, cb)
|
||||||
|
self.failUnlessEqual(result, -18)
|
||||||
|
|
||||||
|
AnotherCallback = WINFUNCTYPE(c_int, c_int, c_int, c_int, c_int)
|
||||||
|
|
||||||
|
# check that the prototype works: we call f with wrong
|
||||||
|
# argument types
|
||||||
|
cb = AnotherCallback(callback)
|
||||||
|
self.assertRaises(ArgumentError, f, -10, cb)
|
||||||
|
|
||||||
|
|
||||||
|
def test_callbacks_2(self):
|
||||||
|
# Can also use simple datatypes as argument type specifiers
|
||||||
|
# for the callback function.
|
||||||
|
# In this case the call receives an instance of that type
|
||||||
|
f = dll._testfunc_callback_i_if
|
||||||
|
f.restype = c_int
|
||||||
|
|
||||||
|
MyCallback = CFUNCTYPE(c_int, c_int)
|
||||||
|
|
||||||
|
f.argtypes = [c_int, MyCallback]
|
||||||
|
|
||||||
|
def callback(value):
|
||||||
|
#print "called back with", value
|
||||||
|
self.failUnlessEqual(type(value), int)
|
||||||
|
return value
|
||||||
|
|
||||||
|
cb = MyCallback(callback)
|
||||||
|
result = f(-10, cb)
|
||||||
|
self.failUnlessEqual(result, -18)
|
||||||
|
|
||||||
|
def test_longlong_callbacks(self):
|
||||||
|
|
||||||
|
f = dll._testfunc_callback_q_qf
|
||||||
|
f.restype = c_longlong
|
||||||
|
|
||||||
|
MyCallback = CFUNCTYPE(c_longlong, c_longlong)
|
||||||
|
|
||||||
|
f.argtypes = [c_longlong, MyCallback]
|
||||||
|
|
||||||
|
def callback(value):
|
||||||
|
self.failUnless(isinstance(value, (int, long)))
|
||||||
|
return value & 0x7FFFFFFF
|
||||||
|
|
||||||
|
cb = MyCallback(callback)
|
||||||
|
|
||||||
|
self.failUnlessEqual(13577625587, f(1000000000000, cb))
|
||||||
|
|
||||||
|
def test_errors(self):
|
||||||
|
self.assertRaises(AttributeError, getattr, dll, "_xxx_yyy")
|
||||||
|
self.assertRaises(ValueError, c_int.in_dll, dll, "_xxx_yyy")
|
||||||
|
|
||||||
|
def test_byval(self):
|
||||||
|
|
||||||
|
class POINT(Structure):
|
||||||
|
_fields_ = [("x", c_int), ("y", c_int)]
|
||||||
|
|
||||||
|
# without prototype
|
||||||
|
ptin = POINT(1, 2)
|
||||||
|
ptout = POINT()
|
||||||
|
# EXPORT int _testfunc_byval(point in, point *pout)
|
||||||
|
result = dll._testfunc_byval(ptin, byref(ptout))
|
||||||
|
got = result, ptout.x, ptout.y
|
||||||
|
expected = 3, 1, 2
|
||||||
|
self.failUnlessEqual(got, expected)
|
||||||
|
|
||||||
|
# with prototype
|
||||||
|
ptin = POINT(101, 102)
|
||||||
|
ptout = POINT()
|
||||||
|
dll._testfunc_byval.argtypes = (POINT, POINTER(POINT))
|
||||||
|
dll._testfunc_byval.restype = c_int
|
||||||
|
result = dll._testfunc_byval(ptin, byref(ptout))
|
||||||
|
got = result, ptout.x, ptout.y
|
||||||
|
expected = 203, 101, 102
|
||||||
|
self.failUnlessEqual(got, expected)
|
||||||
|
|
||||||
|
def test_struct_return_2H(self):
|
||||||
|
class S2H(Structure):
|
||||||
|
_fields_ = [("x", c_short),
|
||||||
|
("y", c_short)]
|
||||||
|
dll.ret_2h_func.restype = S2H
|
||||||
|
dll.ret_2h_func.argtypes = [S2H]
|
||||||
|
inp = S2H(99, 88)
|
||||||
|
s2h = dll.ret_2h_func(inp)
|
||||||
|
self.failUnlessEqual((s2h.x, s2h.y), (99*2, 88*3))
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
def test_struct_return_2H_stdcall(self):
|
||||||
|
class S2H(Structure):
|
||||||
|
_fields_ = [("x", c_short),
|
||||||
|
("y", c_short)]
|
||||||
|
|
||||||
|
windll.s_ret_2h_func.restype = S2H
|
||||||
|
windll.s_ret_2h_func.argtypes = [S2H]
|
||||||
|
s2h = windll.s_ret_2h_func(S2H(99, 88))
|
||||||
|
self.failUnlessEqual((s2h.x, s2h.y), (99*2, 88*3))
|
||||||
|
|
||||||
|
def test_struct_return_8H(self):
|
||||||
|
class S8I(Structure):
|
||||||
|
_fields_ = [("a", c_int),
|
||||||
|
("b", c_int),
|
||||||
|
("c", c_int),
|
||||||
|
("d", c_int),
|
||||||
|
("e", c_int),
|
||||||
|
("f", c_int),
|
||||||
|
("g", c_int),
|
||||||
|
("h", c_int)]
|
||||||
|
dll.ret_8i_func.restype = S8I
|
||||||
|
dll.ret_8i_func.argtypes = [S8I]
|
||||||
|
inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
|
||||||
|
s8i = dll.ret_8i_func(inp)
|
||||||
|
self.failUnlessEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h),
|
||||||
|
(9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
def test_struct_return_8H_stdcall(self):
|
||||||
|
class S8I(Structure):
|
||||||
|
_fields_ = [("a", c_int),
|
||||||
|
("b", c_int),
|
||||||
|
("c", c_int),
|
||||||
|
("d", c_int),
|
||||||
|
("e", c_int),
|
||||||
|
("f", c_int),
|
||||||
|
("g", c_int),
|
||||||
|
("h", c_int)]
|
||||||
|
windll.s_ret_8i_func.restype = S8I
|
||||||
|
windll.s_ret_8i_func.argtypes = [S8I]
|
||||||
|
inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
|
||||||
|
s8i = windll.s_ret_8i_func(inp)
|
||||||
|
self.failUnlessEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h),
|
||||||
|
(9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
42
Lib/ctypes/test/test_incomplete.py
Normal file
42
Lib/ctypes/test/test_incomplete.py
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
#
|
||||||
|
# The incomplete pointer example from the tutorial
|
||||||
|
#
|
||||||
|
|
||||||
|
class MyTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_incomplete_example(self):
|
||||||
|
lpcell = POINTER("cell")
|
||||||
|
class cell(Structure):
|
||||||
|
_fields_ = [("name", c_char_p),
|
||||||
|
("next", lpcell)]
|
||||||
|
|
||||||
|
SetPointerType(lpcell, cell)
|
||||||
|
|
||||||
|
c1 = cell()
|
||||||
|
c1.name = "foo"
|
||||||
|
c2 = cell()
|
||||||
|
c2.name = "bar"
|
||||||
|
|
||||||
|
c1.next = pointer(c2)
|
||||||
|
c2.next = pointer(c1)
|
||||||
|
|
||||||
|
p = c1
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for i in range(8):
|
||||||
|
result.append(p.name)
|
||||||
|
p = p.next[0]
|
||||||
|
self.failUnlessEqual(result, ["foo", "bar"] * 4)
|
||||||
|
|
||||||
|
# to not leak references, we must clean _pointer_type_cache
|
||||||
|
from ctypes import _pointer_type_cache
|
||||||
|
del _pointer_type_cache[cell]
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
40
Lib/ctypes/test/test_init.py
Normal file
40
Lib/ctypes/test/test_init.py
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
from ctypes import *
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_int),
|
||||||
|
("b", c_int)]
|
||||||
|
new_was_called = False
|
||||||
|
|
||||||
|
def __new__(cls):
|
||||||
|
result = super(X, cls).__new__(cls)
|
||||||
|
result.new_was_called = True
|
||||||
|
return result
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.a = 9
|
||||||
|
self.b = 12
|
||||||
|
|
||||||
|
class Y(Structure):
|
||||||
|
_fields_ = [("x", X)]
|
||||||
|
|
||||||
|
|
||||||
|
class InitTest(unittest.TestCase):
|
||||||
|
def test_get(self):
|
||||||
|
# make sure the only accessing a nested structure
|
||||||
|
# doesn't call the structure's __new__ and __init__
|
||||||
|
y = Y()
|
||||||
|
self.failUnlessEqual((y.x.a, y.x.b), (0, 0))
|
||||||
|
self.failUnlessEqual(y.x.new_was_called, False)
|
||||||
|
|
||||||
|
# But explicitely creating an X structure calls __new__ and __init__, of course.
|
||||||
|
x = X()
|
||||||
|
self.failUnlessEqual((x.a, x.b), (9, 12))
|
||||||
|
self.failUnlessEqual(x.new_was_called, True)
|
||||||
|
|
||||||
|
y.x = x
|
||||||
|
self.failUnlessEqual((y.x.a, y.x.b), (9, 12))
|
||||||
|
self.failUnlessEqual(y.x.new_was_called, False)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
5
Lib/ctypes/test/test_integers.py
Normal file
5
Lib/ctypes/test/test_integers.py
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
# superseeded by test_numbers.py
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
103
Lib/ctypes/test/test_internals.py
Normal file
103
Lib/ctypes/test/test_internals.py
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
# This tests the internal _objects attribute
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
from sys import getrefcount as grc
|
||||||
|
|
||||||
|
# XXX This test must be reviewed for correctness!!!
|
||||||
|
|
||||||
|
"""
|
||||||
|
ctypes' types are container types.
|
||||||
|
|
||||||
|
They have an internal memory block, which only consists of some bytes,
|
||||||
|
but it has to keep references to other objects as well. This is not
|
||||||
|
really needed for trivial C types like int or char, but it is important
|
||||||
|
for aggregate types like strings or pointers in particular.
|
||||||
|
|
||||||
|
What about pointers?
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
class ObjectsTestCase(unittest.TestCase):
|
||||||
|
def failUnlessSame(self, a, b):
|
||||||
|
self.failUnlessEqual(id(a), id(b))
|
||||||
|
|
||||||
|
def test_ints(self):
|
||||||
|
i = 42000123
|
||||||
|
self.failUnlessEqual(3, grc(i))
|
||||||
|
ci = c_int(i)
|
||||||
|
self.failUnlessEqual(3, grc(i))
|
||||||
|
self.failUnlessEqual(ci._objects, None)
|
||||||
|
|
||||||
|
def test_c_char_p(self):
|
||||||
|
s = "Hello, World"
|
||||||
|
self.failUnlessEqual(3, grc(s))
|
||||||
|
cs = c_char_p(s)
|
||||||
|
self.failUnlessEqual(4, grc(s))
|
||||||
|
self.failUnlessSame(cs._objects, s)
|
||||||
|
|
||||||
|
def test_simple_struct(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_int), ("b", c_int)]
|
||||||
|
|
||||||
|
a = 421234
|
||||||
|
b = 421235
|
||||||
|
x = X()
|
||||||
|
self.failUnlessEqual(x._objects, None)
|
||||||
|
x.a = a
|
||||||
|
x.b = b
|
||||||
|
self.failUnlessEqual(x._objects, None)
|
||||||
|
|
||||||
|
def test_embedded_structs(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_int), ("b", c_int)]
|
||||||
|
|
||||||
|
class Y(Structure):
|
||||||
|
_fields_ = [("x", X), ("y", X)]
|
||||||
|
|
||||||
|
y = Y()
|
||||||
|
self.failUnlessEqual(y._objects, None)
|
||||||
|
|
||||||
|
x1, x2 = X(), X()
|
||||||
|
y.x, y.y = x1, x2
|
||||||
|
self.failUnlessEqual(y._objects, {"0": {}, "1": {}})
|
||||||
|
x1.a, x2.b = 42, 93
|
||||||
|
self.failUnlessEqual(y._objects, {"0": {}, "1": {}})
|
||||||
|
|
||||||
|
def test_xxx(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_char_p), ("b", c_char_p)]
|
||||||
|
|
||||||
|
class Y(Structure):
|
||||||
|
_fields_ = [("x", X), ("y", X)]
|
||||||
|
|
||||||
|
s1 = "Hello, World"
|
||||||
|
s2 = "Hallo, Welt"
|
||||||
|
|
||||||
|
x = X()
|
||||||
|
x.a = s1
|
||||||
|
x.b = s2
|
||||||
|
self.failUnlessEqual(x._objects, {"0": s1, "1": s2})
|
||||||
|
|
||||||
|
y = Y()
|
||||||
|
y.x = x
|
||||||
|
self.failUnlessEqual(y._objects, {"0": {"0": s1, "1": s2}})
|
||||||
|
## x = y.x
|
||||||
|
## del y
|
||||||
|
## print x._b_base_._objects
|
||||||
|
|
||||||
|
def test_ptr_struct(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("data", POINTER(c_int))]
|
||||||
|
|
||||||
|
A = c_int*4
|
||||||
|
a = A(11, 22, 33, 44)
|
||||||
|
self.failUnlessEqual(a._objects, None)
|
||||||
|
|
||||||
|
x = X()
|
||||||
|
x.data = a
|
||||||
|
##XXX print x._objects
|
||||||
|
##XXX print x.data[0]
|
||||||
|
##XXX print x.data._objects
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
144
Lib/ctypes/test/test_keeprefs.py
Normal file
144
Lib/ctypes/test/test_keeprefs.py
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
from ctypes import *
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class SimpleTestCase(unittest.TestCase):
|
||||||
|
def test_cint(self):
|
||||||
|
x = c_int()
|
||||||
|
self.assertEquals(x._objects, None)
|
||||||
|
x.value = 42
|
||||||
|
self.assertEquals(x._objects, None)
|
||||||
|
x = c_int(99)
|
||||||
|
self.assertEquals(x._objects, None)
|
||||||
|
|
||||||
|
def test_ccharp(self):
|
||||||
|
x = c_char_p()
|
||||||
|
self.assertEquals(x._objects, None)
|
||||||
|
x.value = "abc"
|
||||||
|
self.assertEquals(x._objects, "abc")
|
||||||
|
x = c_char_p("spam")
|
||||||
|
self.assertEquals(x._objects, "spam")
|
||||||
|
|
||||||
|
class StructureTestCase(unittest.TestCase):
|
||||||
|
def test_cint_struct(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_int),
|
||||||
|
("b", c_int)]
|
||||||
|
|
||||||
|
x = X()
|
||||||
|
self.assertEquals(x._objects, None)
|
||||||
|
x.a = 42
|
||||||
|
x.b = 99
|
||||||
|
self.assertEquals(x._objects, None)
|
||||||
|
|
||||||
|
def test_ccharp_struct(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_char_p),
|
||||||
|
("b", c_char_p)]
|
||||||
|
x = X()
|
||||||
|
self.assertEquals(x._objects, None)
|
||||||
|
|
||||||
|
x.a = "spam"
|
||||||
|
x.b = "foo"
|
||||||
|
self.assertEquals(x._objects, {"0": "spam", "1": "foo"})
|
||||||
|
|
||||||
|
def test_struct_struct(self):
|
||||||
|
class POINT(Structure):
|
||||||
|
_fields_ = [("x", c_int), ("y", c_int)]
|
||||||
|
class RECT(Structure):
|
||||||
|
_fields_ = [("ul", POINT), ("lr", POINT)]
|
||||||
|
|
||||||
|
r = RECT()
|
||||||
|
r.ul.x = 0
|
||||||
|
r.ul.y = 1
|
||||||
|
r.lr.x = 2
|
||||||
|
r.lr.y = 3
|
||||||
|
self.assertEquals(r._objects, None)
|
||||||
|
|
||||||
|
r = RECT()
|
||||||
|
pt = POINT(1, 2)
|
||||||
|
r.ul = pt
|
||||||
|
self.assertEquals(r._objects, {'0': {}})
|
||||||
|
r.ul.x = 22
|
||||||
|
r.ul.y = 44
|
||||||
|
self.assertEquals(r._objects, {'0': {}})
|
||||||
|
|
||||||
|
class ArrayTestCase(unittest.TestCase):
|
||||||
|
def test_cint_array(self):
|
||||||
|
INTARR = c_int * 3
|
||||||
|
|
||||||
|
ia = INTARR()
|
||||||
|
self.assertEquals(ia._objects, None)
|
||||||
|
ia[0] = 1
|
||||||
|
ia[1] = 2
|
||||||
|
ia[2] = 3
|
||||||
|
self.assertEquals(ia._objects, None)
|
||||||
|
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("x", c_int),
|
||||||
|
("a", INTARR)]
|
||||||
|
|
||||||
|
x = X()
|
||||||
|
x.x = 1000
|
||||||
|
x.a[0] = 42
|
||||||
|
x.a[1] = 96
|
||||||
|
self.assertEquals(x._objects, None)
|
||||||
|
x.a = ia
|
||||||
|
self.assertEquals(x._objects, {'1': {}})
|
||||||
|
|
||||||
|
class PointerTestCase(unittest.TestCase):
|
||||||
|
def X_test_p_cint(self):
|
||||||
|
x = pointer(c_int(42))
|
||||||
|
print x._objects
|
||||||
|
|
||||||
|
class DeletePointerTestCase(unittest.TestCase):
|
||||||
|
def X_test(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("p", POINTER(c_char_p))]
|
||||||
|
x = X()
|
||||||
|
i = c_char_p("abc def")
|
||||||
|
from sys import getrefcount as grc
|
||||||
|
print "2?", grc(i)
|
||||||
|
x.p = pointer(i)
|
||||||
|
print "3?", grc(i)
|
||||||
|
for i in range(320):
|
||||||
|
c_int(99)
|
||||||
|
x.p[0]
|
||||||
|
print x.p[0]
|
||||||
|
## del x
|
||||||
|
## print "2?", grc(i)
|
||||||
|
## del i
|
||||||
|
import gc
|
||||||
|
gc.collect()
|
||||||
|
for i in range(320):
|
||||||
|
c_int(99)
|
||||||
|
x.p[0]
|
||||||
|
print x.p[0]
|
||||||
|
print x.p.contents
|
||||||
|
## print x._objects
|
||||||
|
|
||||||
|
x.p[0] = "spam spam"
|
||||||
|
## print x.p[0]
|
||||||
|
print "+" * 42
|
||||||
|
print x._objects
|
||||||
|
|
||||||
|
class PointerToStructure(unittest.TestCase):
|
||||||
|
def test(self):
|
||||||
|
class POINT(Structure):
|
||||||
|
_fields_ = [("x", c_int), ("y", c_int)]
|
||||||
|
class RECT(Structure):
|
||||||
|
_fields_ = [("a", POINTER(POINT)),
|
||||||
|
("b", POINTER(POINT))]
|
||||||
|
r = RECT()
|
||||||
|
p1 = POINT(1, 2)
|
||||||
|
|
||||||
|
r.a = pointer(p1)
|
||||||
|
r.b = pointer(p1)
|
||||||
|
## from pprint import pprint as pp
|
||||||
|
## pp(p1._objects)
|
||||||
|
## pp(r._objects)
|
||||||
|
|
||||||
|
r.a[0].x = 42
|
||||||
|
r.a[0].y = 99
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
88
Lib/ctypes/test/test_leaks.py
Normal file
88
Lib/ctypes/test/test_leaks.py
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
import unittest, sys, gc
|
||||||
|
from ctypes import *
|
||||||
|
from ctypes import _pointer_type_cache
|
||||||
|
|
||||||
|
class LeakTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
################
|
||||||
|
|
||||||
|
def make_noncyclic_structures(self, repeat):
|
||||||
|
for i in xrange(repeat):
|
||||||
|
class POINT(Structure):
|
||||||
|
_fields_ = [("x", c_int), ("y", c_int)]
|
||||||
|
class RECT(Structure):
|
||||||
|
_fields_ = [("ul", POINT),
|
||||||
|
("br", POINT)]
|
||||||
|
|
||||||
|
if hasattr(sys, "gettotalrefcount"):
|
||||||
|
|
||||||
|
def test_no_cycles_refcount(self):
|
||||||
|
last_refcount = 0
|
||||||
|
for x in xrange(20):
|
||||||
|
self.make_noncyclic_structures(1000)
|
||||||
|
while gc.collect():
|
||||||
|
pass
|
||||||
|
total_refcount = sys.gettotalrefcount()
|
||||||
|
if last_refcount >= total_refcount:
|
||||||
|
return # test passed
|
||||||
|
last_refcount = total_refcount
|
||||||
|
self.fail("leaking refcounts")
|
||||||
|
|
||||||
|
def test_no_cycles_objcount(self):
|
||||||
|
# not correct - gc.get_objects() returns only thos objects
|
||||||
|
# that the garbage collector tracks. Correct would be to use
|
||||||
|
# sys.getobjects(), but this is only available in debug build.
|
||||||
|
last_objcount = 0
|
||||||
|
for x in xrange(20):
|
||||||
|
self.make_noncyclic_structures(1000)
|
||||||
|
while gc.collect():
|
||||||
|
pass
|
||||||
|
total_objcount = gc.get_objects()
|
||||||
|
if last_objcount >= total_objcount:
|
||||||
|
return # test passed
|
||||||
|
last_objcount = total_objcount
|
||||||
|
self.fail("leaking objects")
|
||||||
|
|
||||||
|
################
|
||||||
|
|
||||||
|
def make_cyclic_structures(self, repeat):
|
||||||
|
for i in xrange(repeat):
|
||||||
|
PLIST = POINTER("LIST")
|
||||||
|
class LIST(Structure):
|
||||||
|
_fields_ = [("pnext", PLIST)]
|
||||||
|
SetPointerType(PLIST, LIST)
|
||||||
|
del _pointer_type_cache[LIST] # XXX should this be a weakkeydict?
|
||||||
|
|
||||||
|
if hasattr(sys, "gettotalrefcount"):
|
||||||
|
|
||||||
|
def test_cycles_refcount(self):
|
||||||
|
last_refcount = 0
|
||||||
|
for x in xrange(5):
|
||||||
|
self.make_cyclic_structures(1000)
|
||||||
|
while gc.collect():
|
||||||
|
pass
|
||||||
|
total_refcount = sys.gettotalrefcount()
|
||||||
|
if last_refcount >= total_refcount:
|
||||||
|
return
|
||||||
|
last_refcount = total_refcount
|
||||||
|
self.fail("leaking refcounts")
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
def test_cycles_objcount(self):
|
||||||
|
# not correct - gc.get_objects() returns only thos objects
|
||||||
|
# that the garbage collector tracks. Correct would be to use
|
||||||
|
# sys.getobjects(), but this is only available in debug build.
|
||||||
|
last_objcount = 0
|
||||||
|
for x in xrange(8):
|
||||||
|
self.make_cyclic_structures(1000)
|
||||||
|
while gc.collect():
|
||||||
|
pass
|
||||||
|
total_objcount = len(gc.get_objects())
|
||||||
|
if last_objcount >= total_objcount:
|
||||||
|
return
|
||||||
|
last_objcount = total_objcount
|
||||||
|
self.fail("leaking objects")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
30
Lib/ctypes/test/test_libc.py
Normal file
30
Lib/ctypes/test/test_libc.py
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
import sys, os
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from ctypes import *
|
||||||
|
import _ctypes_test
|
||||||
|
|
||||||
|
lib = cdll.load(_ctypes_test.__file__)
|
||||||
|
|
||||||
|
class LibTest(unittest.TestCase):
|
||||||
|
def test_sqrt(self):
|
||||||
|
lib.my_sqrt.argtypes = c_double,
|
||||||
|
lib.my_sqrt.restype = c_double
|
||||||
|
self.failUnlessEqual(lib.my_sqrt(4.0), 2.0)
|
||||||
|
import math
|
||||||
|
self.failUnlessEqual(lib.my_sqrt(2.0), math.sqrt(2.0))
|
||||||
|
|
||||||
|
def test_qsort(self):
|
||||||
|
comparefunc = CFUNCTYPE(c_int, POINTER(c_char), POINTER(c_char))
|
||||||
|
lib.my_qsort.argtypes = c_void_p, c_size_t, c_size_t, comparefunc
|
||||||
|
lib.my_qsort.restype = None
|
||||||
|
|
||||||
|
def sort(a, b):
|
||||||
|
return cmp(a[0], b[0])
|
||||||
|
|
||||||
|
chars = create_string_buffer("spam, spam, and spam")
|
||||||
|
lib.my_qsort(chars, len(chars)-1, sizeof(c_char), comparefunc(sort))
|
||||||
|
self.failUnlessEqual(chars.raw, " ,,aaaadmmmnpppsss\x00")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
41
Lib/ctypes/test/test_loading.py
Normal file
41
Lib/ctypes/test/test_loading.py
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
from ctypes import *
|
||||||
|
import sys, unittest
|
||||||
|
import os, StringIO
|
||||||
|
|
||||||
|
class LoaderTest(unittest.TestCase):
|
||||||
|
|
||||||
|
unknowndll = "xxrandomnamexx"
|
||||||
|
|
||||||
|
def test_load(self):
|
||||||
|
if os.name == "nt":
|
||||||
|
name = "msvcrt"
|
||||||
|
elif os.name == "ce":
|
||||||
|
name = "coredll"
|
||||||
|
elif sys.platform == "darwin":
|
||||||
|
name = "libc.dylib"
|
||||||
|
elif sys.platform.startswith("freebsd"):
|
||||||
|
name = "libc.so"
|
||||||
|
elif sys.platform == "sunos5":
|
||||||
|
name = "libc.so"
|
||||||
|
else:
|
||||||
|
name = "libc.so.6"
|
||||||
|
cdll.load(name)
|
||||||
|
self.assertRaises(OSError, cdll.load, self.unknowndll)
|
||||||
|
|
||||||
|
def test_load_version(self):
|
||||||
|
version = "6"
|
||||||
|
name = "c"
|
||||||
|
if sys.platform == "linux2":
|
||||||
|
cdll.load_version(name, version)
|
||||||
|
# linux uses version, libc 9 should not exist
|
||||||
|
self.assertRaises(OSError, cdll.load_version, name, "9")
|
||||||
|
self.assertRaises(OSError, cdll.load_version, self.unknowndll, "")
|
||||||
|
|
||||||
|
if os.name == "posix" and sys.platform != "sunos5":
|
||||||
|
def test_find(self):
|
||||||
|
name = "c"
|
||||||
|
cdll.find(name)
|
||||||
|
self.assertRaises(OSError, cdll.find, self.unknowndll)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
62
Lib/ctypes/test/test_macholib.py
Normal file
62
Lib/ctypes/test/test_macholib.py
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
# Bob Ippolito:
|
||||||
|
"""
|
||||||
|
Ok.. the code to find the filename for __getattr__ should look
|
||||||
|
something like:
|
||||||
|
|
||||||
|
import os
|
||||||
|
from macholib.dyld import dyld_find
|
||||||
|
|
||||||
|
def find_lib(name):
|
||||||
|
possible = ['lib'+name+'.dylib', name+'.dylib',
|
||||||
|
name+'.framework/'+name]
|
||||||
|
for dylib in possible:
|
||||||
|
try:
|
||||||
|
return os.path.realpath(dyld_find(dylib))
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
raise ValueError, "%s not found" % (name,)
|
||||||
|
|
||||||
|
It'll have output like this:
|
||||||
|
|
||||||
|
>>> find_lib('pthread')
|
||||||
|
'/usr/lib/libSystem.B.dylib'
|
||||||
|
>>> find_lib('z')
|
||||||
|
'/usr/lib/libz.1.dylib'
|
||||||
|
>>> find_lib('IOKit')
|
||||||
|
'/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit'
|
||||||
|
|
||||||
|
-bob
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ctypes.macholib.dyld import dyld_find
|
||||||
|
|
||||||
|
def find_lib(name):
|
||||||
|
possible = ['lib'+name+'.dylib', name+'.dylib', name+'.framework/'+name]
|
||||||
|
for dylib in possible:
|
||||||
|
try:
|
||||||
|
return os.path.realpath(dyld_find(dylib))
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
raise ValueError, "%s not found" % (name,)
|
||||||
|
|
||||||
|
class MachOTest(unittest.TestCase):
|
||||||
|
if sys.platform == "darwin":
|
||||||
|
def test_find(self):
|
||||||
|
|
||||||
|
self.failUnlessEqual(find_lib('pthread'),
|
||||||
|
'/usr/lib/libSystem.B.dylib')
|
||||||
|
|
||||||
|
result = find_lib('z')
|
||||||
|
self.failUnless(result.startswith('/usr/lib/libz.1'))
|
||||||
|
self.failUnless(result.endswith('.dylib'))
|
||||||
|
|
||||||
|
self.failUnlessEqual(find_lib('IOKit'),
|
||||||
|
'/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit')
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
59
Lib/ctypes/test/test_memfunctions.py
Normal file
59
Lib/ctypes/test/test_memfunctions.py
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
class MemFunctionsTest(unittest.TestCase):
|
||||||
|
def test_memmove(self):
|
||||||
|
# large buffers apparently increase the chance that the memory
|
||||||
|
# is allocated in high address space.
|
||||||
|
a = create_string_buffer(1000000)
|
||||||
|
p = "Hello, World"
|
||||||
|
result = memmove(a, p, len(p))
|
||||||
|
self.failUnlessEqual(a.value, "Hello, World")
|
||||||
|
|
||||||
|
self.failUnlessEqual(string_at(result), "Hello, World")
|
||||||
|
self.failUnlessEqual(string_at(result, 5), "Hello")
|
||||||
|
self.failUnlessEqual(string_at(result, 16), "Hello, World\0\0\0\0")
|
||||||
|
|
||||||
|
def test_memset(self):
|
||||||
|
a = create_string_buffer(1000000)
|
||||||
|
result = memset(a, ord('x'), 16)
|
||||||
|
self.failUnlessEqual(a.value, "xxxxxxxxxxxxxxxx")
|
||||||
|
|
||||||
|
self.failUnlessEqual(string_at(result), "xxxxxxxxxxxxxxxx")
|
||||||
|
self.failUnlessEqual(string_at(a), "xxxxxxxxxxxxxxxx")
|
||||||
|
self.failUnlessEqual(string_at(a, 20), "xxxxxxxxxxxxxxxx\0\0\0\0")
|
||||||
|
|
||||||
|
def test_cast(self):
|
||||||
|
a = (c_ubyte * 32)(*map(ord, "abcdef"))
|
||||||
|
self.failUnlessEqual(cast(a, c_char_p).value, "abcdef")
|
||||||
|
self.failUnlessEqual(cast(a, POINTER(c_byte))[:7],
|
||||||
|
[97, 98, 99, 100, 101, 102, 0])
|
||||||
|
|
||||||
|
def test_string_at(self):
|
||||||
|
s = string_at("foo bar")
|
||||||
|
# XXX The following may be wrong, depending on how Python
|
||||||
|
# manages string instances
|
||||||
|
self.failUnlessEqual(2, sys.getrefcount(s))
|
||||||
|
self.failUnless(s, "foo bar")
|
||||||
|
|
||||||
|
self.failUnlessEqual(string_at("foo bar", 8), "foo bar\0")
|
||||||
|
self.failUnlessEqual(string_at("foo bar", 3), "foo")
|
||||||
|
|
||||||
|
try:
|
||||||
|
create_unicode_buffer
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
def test_wstring_at(self):
|
||||||
|
p = create_unicode_buffer("Hello, World")
|
||||||
|
a = create_unicode_buffer(1000000)
|
||||||
|
result = memmove(a, p, len(p) * sizeof(c_wchar))
|
||||||
|
self.failUnlessEqual(a.value, "Hello, World")
|
||||||
|
|
||||||
|
self.failUnlessEqual(wstring_at(a), "Hello, World")
|
||||||
|
self.failUnlessEqual(wstring_at(a, 5), "Hello")
|
||||||
|
self.failUnlessEqual(wstring_at(a, 16), "Hello, World\0\0\0\0")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
243
Lib/ctypes/test/test_numbers.py
Normal file
243
Lib/ctypes/test/test_numbers.py
Normal file
|
|
@ -0,0 +1,243 @@
|
||||||
|
from ctypes import *
|
||||||
|
import unittest
|
||||||
|
import sys, struct
|
||||||
|
|
||||||
|
def valid_ranges(*types):
|
||||||
|
# given a sequence of numeric types, collect their _type_
|
||||||
|
# attribute, which is a single format character compatible with
|
||||||
|
# the struct module, use the struct module to calculate the
|
||||||
|
# minimum and maximum value allowed for this format.
|
||||||
|
# Returns a list of (min, max) values.
|
||||||
|
result = []
|
||||||
|
for t in types:
|
||||||
|
fmt = t._type_
|
||||||
|
size = struct.calcsize(fmt)
|
||||||
|
a = struct.unpack(fmt, ("\x00"*32)[:size])[0]
|
||||||
|
b = struct.unpack(fmt, ("\xFF"*32)[:size])[0]
|
||||||
|
c = struct.unpack(fmt, ("\x7F"+"\x00"*32)[:size])[0]
|
||||||
|
d = struct.unpack(fmt, ("\x80"+"\xFF"*32)[:size])[0]
|
||||||
|
result.append((min(a, b, c, d), max(a, b, c, d)))
|
||||||
|
return result
|
||||||
|
|
||||||
|
ArgType = type(c_int(0)._as_parameter_)
|
||||||
|
|
||||||
|
unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong]
|
||||||
|
signed_types = [c_byte, c_short, c_int, c_long, c_longlong]
|
||||||
|
|
||||||
|
float_types = [c_double, c_float]
|
||||||
|
|
||||||
|
try:
|
||||||
|
c_ulonglong
|
||||||
|
c_longlong
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
unsigned_types.append(c_ulonglong)
|
||||||
|
signed_types.append(c_longlong)
|
||||||
|
|
||||||
|
unsigned_ranges = valid_ranges(*unsigned_types)
|
||||||
|
signed_ranges = valid_ranges(*signed_types)
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
class NumberTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_default_init(self):
|
||||||
|
# default values are set to zero
|
||||||
|
for t in signed_types + unsigned_types + float_types:
|
||||||
|
self.failUnlessEqual(t().value, 0)
|
||||||
|
|
||||||
|
def test_unsigned_values(self):
|
||||||
|
# the value given to the constructor is available
|
||||||
|
# as the 'value' attribute
|
||||||
|
for t, (l, h) in zip(unsigned_types, unsigned_ranges):
|
||||||
|
self.failUnlessEqual(t(l).value, l)
|
||||||
|
self.failUnlessEqual(t(h).value, h)
|
||||||
|
|
||||||
|
def test_signed_values(self):
|
||||||
|
# see above
|
||||||
|
for t, (l, h) in zip(signed_types, signed_ranges):
|
||||||
|
self.failUnlessEqual(t(l).value, l)
|
||||||
|
self.failUnlessEqual(t(h).value, h)
|
||||||
|
|
||||||
|
def test_typeerror(self):
|
||||||
|
# Only numbers are allowed in the contructor,
|
||||||
|
# otherwise TypeError is raised
|
||||||
|
for t in signed_types + unsigned_types + float_types:
|
||||||
|
self.assertRaises(TypeError, t, "")
|
||||||
|
self.assertRaises(TypeError, t, None)
|
||||||
|
|
||||||
|
## def test_valid_ranges(self):
|
||||||
|
## # invalid values of the correct type
|
||||||
|
## # raise ValueError (not OverflowError)
|
||||||
|
## for t, (l, h) in zip(unsigned_types, unsigned_ranges):
|
||||||
|
## self.assertRaises(ValueError, t, l-1)
|
||||||
|
## self.assertRaises(ValueError, t, h+1)
|
||||||
|
|
||||||
|
def test_from_param(self):
|
||||||
|
# the from_param class method attribute always
|
||||||
|
# returns PyCArgObject instances
|
||||||
|
for t in signed_types + unsigned_types + float_types:
|
||||||
|
self.failUnlessEqual(ArgType, type(t.from_param(0)))
|
||||||
|
|
||||||
|
def test_as_parameter(self):
|
||||||
|
# The _as_parameter_ property must also
|
||||||
|
# be a PyCArgObject instance
|
||||||
|
for t in signed_types + unsigned_types + float_types:
|
||||||
|
parm = t()._as_parameter_
|
||||||
|
self.failUnlessEqual(ArgType, type(parm))
|
||||||
|
|
||||||
|
# _as_parameter_ is readonly!
|
||||||
|
#
|
||||||
|
# Python 2.3 and 2.4 raise a TypeError when trying to set
|
||||||
|
# a readonly attribute, 2.5 raises an AttributeError.
|
||||||
|
self.assertRaises((AttributeError, TypeError), setattr, t(), "_as_parameter_", None)
|
||||||
|
|
||||||
|
def test_byref(self):
|
||||||
|
# calling byref returns also a PyCArgObject instance
|
||||||
|
for t in signed_types + unsigned_types + float_types:
|
||||||
|
parm = byref(t())
|
||||||
|
self.failUnlessEqual(ArgType, type(parm))
|
||||||
|
|
||||||
|
|
||||||
|
def test_floats(self):
|
||||||
|
# c_float and c_double can be created from
|
||||||
|
# Python int, long and float
|
||||||
|
for t in float_types:
|
||||||
|
self.failUnlessEqual(t(2.0).value, 2.0)
|
||||||
|
self.failUnlessEqual(t(2).value, 2.0)
|
||||||
|
self.failUnlessEqual(t(2L).value, 2.0)
|
||||||
|
|
||||||
|
def test_integers(self):
|
||||||
|
# integers cannot be constructed from floats
|
||||||
|
for t in signed_types + unsigned_types:
|
||||||
|
self.assertRaises(TypeError, t, 3.14)
|
||||||
|
|
||||||
|
def test_sizes(self):
|
||||||
|
for t in signed_types + unsigned_types + float_types:
|
||||||
|
size = struct.calcsize(t._type_)
|
||||||
|
# sizeof of the type...
|
||||||
|
self.failUnlessEqual(sizeof(t), size)
|
||||||
|
# and sizeof of an instance
|
||||||
|
self.failUnlessEqual(sizeof(t()), size)
|
||||||
|
|
||||||
|
def test_alignments(self):
|
||||||
|
for t in signed_types + unsigned_types + float_types:
|
||||||
|
code = t._type_ # the typecode
|
||||||
|
align = struct.calcsize("c%c" % code) - struct.calcsize(code)
|
||||||
|
|
||||||
|
# alignment of the type...
|
||||||
|
self.failUnlessEqual((code, alignment(t)),
|
||||||
|
(code, align))
|
||||||
|
# and alignment of an instance
|
||||||
|
self.failUnlessEqual((code, alignment(t())),
|
||||||
|
(code, align))
|
||||||
|
|
||||||
|
def test_int_from_address(self):
|
||||||
|
from array import array
|
||||||
|
for t in signed_types + unsigned_types:
|
||||||
|
# the array module doesn't suppport all format codes
|
||||||
|
# (no 'q' or 'Q')
|
||||||
|
try:
|
||||||
|
array(t._type_)
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
a = array(t._type_, [100])
|
||||||
|
|
||||||
|
# v now is an integer at an 'external' memory location
|
||||||
|
v = t.from_address(a.buffer_info()[0])
|
||||||
|
self.failUnlessEqual(v.value, a[0])
|
||||||
|
self.failUnlessEqual(type(v), t)
|
||||||
|
|
||||||
|
# changing the value at the memory location changes v's value also
|
||||||
|
a[0] = 42
|
||||||
|
self.failUnlessEqual(v.value, a[0])
|
||||||
|
|
||||||
|
|
||||||
|
def test_float_from_address(self):
|
||||||
|
from array import array
|
||||||
|
for t in float_types:
|
||||||
|
a = array(t._type_, [3.14])
|
||||||
|
v = t.from_address(a.buffer_info()[0])
|
||||||
|
self.failUnlessEqual(v.value, a[0])
|
||||||
|
self.failUnless(type(v) is t)
|
||||||
|
a[0] = 2.3456e17
|
||||||
|
self.failUnlessEqual(v.value, a[0])
|
||||||
|
self.failUnless(type(v) is t)
|
||||||
|
|
||||||
|
def test_char_from_address(self):
|
||||||
|
from ctypes import c_char
|
||||||
|
from array import array
|
||||||
|
|
||||||
|
a = array('c', 'x')
|
||||||
|
v = c_char.from_address(a.buffer_info()[0])
|
||||||
|
self.failUnlessEqual(v.value, a[0])
|
||||||
|
self.failUnless(type(v) is c_char)
|
||||||
|
|
||||||
|
a[0] = '?'
|
||||||
|
self.failUnlessEqual(v.value, a[0])
|
||||||
|
|
||||||
|
def test_init(self):
|
||||||
|
# c_int() can be initialized from Python's int, and c_int.
|
||||||
|
# Not from c_long or so, which seems strange, abd should
|
||||||
|
# probably be changed:
|
||||||
|
self.assertRaises(TypeError, c_int, c_long(42))
|
||||||
|
|
||||||
|
## def test_perf(self):
|
||||||
|
## check_perf()
|
||||||
|
|
||||||
|
from ctypes import _SimpleCData
|
||||||
|
class c_int_S(_SimpleCData):
|
||||||
|
_type_ = "i"
|
||||||
|
__slots__ = []
|
||||||
|
|
||||||
|
def run_test(rep, msg, func, arg=None):
|
||||||
|
## items = [None] * rep
|
||||||
|
items = range(rep)
|
||||||
|
from time import clock
|
||||||
|
if arg is not None:
|
||||||
|
start = clock()
|
||||||
|
for i in items:
|
||||||
|
func(arg); func(arg); func(arg); func(arg); func(arg)
|
||||||
|
stop = clock()
|
||||||
|
else:
|
||||||
|
start = clock()
|
||||||
|
for i in items:
|
||||||
|
func(); func(); func(); func(); func()
|
||||||
|
stop = clock()
|
||||||
|
print "%15s: %.2f us" % (msg, ((stop-start)*1e6/5/rep))
|
||||||
|
|
||||||
|
def check_perf():
|
||||||
|
# Construct 5 objects
|
||||||
|
from ctypes import c_int
|
||||||
|
|
||||||
|
REP = 200000
|
||||||
|
|
||||||
|
run_test(REP, "int()", int)
|
||||||
|
run_test(REP, "int(999)", int)
|
||||||
|
run_test(REP, "c_int()", c_int)
|
||||||
|
run_test(REP, "c_int(999)", c_int)
|
||||||
|
run_test(REP, "c_int_S()", c_int_S)
|
||||||
|
run_test(REP, "c_int_S(999)", c_int_S)
|
||||||
|
|
||||||
|
# Python 2.3 -OO, win2k, P4 700 MHz:
|
||||||
|
#
|
||||||
|
# int(): 0.87 us
|
||||||
|
# int(999): 0.87 us
|
||||||
|
# c_int(): 3.35 us
|
||||||
|
# c_int(999): 3.34 us
|
||||||
|
# c_int_S(): 3.23 us
|
||||||
|
# c_int_S(999): 3.24 us
|
||||||
|
|
||||||
|
# Python 2.2 -OO, win2k, P4 700 MHz:
|
||||||
|
#
|
||||||
|
# int(): 0.89 us
|
||||||
|
# int(999): 0.89 us
|
||||||
|
# c_int(): 9.99 us
|
||||||
|
# c_int(999): 10.02 us
|
||||||
|
# c_int_S(): 9.87 us
|
||||||
|
# c_int_S(999): 9.85 us
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
## check_perf()
|
||||||
|
unittest.main()
|
||||||
153
Lib/ctypes/test/test_parameters.py
Normal file
153
Lib/ctypes/test/test_parameters.py
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
import unittest, sys
|
||||||
|
|
||||||
|
class SimpleTypesTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
import ctypes
|
||||||
|
try:
|
||||||
|
from _ctypes import set_conversion_mode
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.prev_conv_mode = set_conversion_mode("ascii", "strict")
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
try:
|
||||||
|
from _ctypes import set_conversion_mode
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
set_conversion_mode(*self.prev_conv_mode)
|
||||||
|
|
||||||
|
|
||||||
|
def test_subclasses(self):
|
||||||
|
from ctypes import c_void_p, c_char_p
|
||||||
|
# ctypes 0.9.5 and before did overwrite from_param in SimpleType_new
|
||||||
|
class CVOIDP(c_void_p):
|
||||||
|
def from_param(cls, value):
|
||||||
|
return value * 2
|
||||||
|
from_param = classmethod(from_param)
|
||||||
|
|
||||||
|
class CCHARP(c_char_p):
|
||||||
|
def from_param(cls, value):
|
||||||
|
return value * 4
|
||||||
|
from_param = classmethod(from_param)
|
||||||
|
|
||||||
|
self.failUnlessEqual(CVOIDP.from_param("abc"), "abcabc")
|
||||||
|
self.failUnlessEqual(CCHARP.from_param("abc"), "abcabcabcabc")
|
||||||
|
|
||||||
|
try:
|
||||||
|
from ctypes import c_wchar_p
|
||||||
|
except ImportError:
|
||||||
|
return
|
||||||
|
|
||||||
|
class CWCHARP(c_wchar_p):
|
||||||
|
def from_param(cls, value):
|
||||||
|
return value * 3
|
||||||
|
from_param = classmethod(from_param)
|
||||||
|
|
||||||
|
self.failUnlessEqual(CWCHARP.from_param("abc"), "abcabcabc")
|
||||||
|
|
||||||
|
# XXX Replace by c_char_p tests
|
||||||
|
def test_cstrings(self):
|
||||||
|
from ctypes import c_char_p, byref
|
||||||
|
|
||||||
|
# c_char_p.from_param on a Python String packs the string
|
||||||
|
# into a cparam object
|
||||||
|
s = "123"
|
||||||
|
self.failUnless(c_char_p.from_param(s)._obj is s)
|
||||||
|
|
||||||
|
# new in 0.9.1: convert (encode) unicode to ascii
|
||||||
|
self.failUnlessEqual(c_char_p.from_param(u"123")._obj, "123")
|
||||||
|
self.assertRaises(UnicodeEncodeError, c_char_p.from_param, u"123\377")
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, c_char_p.from_param, 42)
|
||||||
|
|
||||||
|
# calling c_char_p.from_param with a c_char_p instance
|
||||||
|
# returns the argument itself:
|
||||||
|
a = c_char_p("123")
|
||||||
|
self.failUnless(c_char_p.from_param(a) is a)
|
||||||
|
|
||||||
|
def test_cw_strings(self):
|
||||||
|
from ctypes import byref
|
||||||
|
try:
|
||||||
|
from ctypes import c_wchar_p
|
||||||
|
except ImportError:
|
||||||
|
## print "(No c_wchar_p)"
|
||||||
|
return
|
||||||
|
s = u"123"
|
||||||
|
if sys.platform == "win32":
|
||||||
|
self.failUnless(c_wchar_p.from_param(s)._obj is s)
|
||||||
|
self.assertRaises(TypeError, c_wchar_p.from_param, 42)
|
||||||
|
|
||||||
|
# new in 0.9.1: convert (decode) ascii to unicode
|
||||||
|
self.failUnlessEqual(c_wchar_p.from_param("123")._obj, u"123")
|
||||||
|
self.assertRaises(UnicodeDecodeError, c_wchar_p.from_param, "123\377")
|
||||||
|
|
||||||
|
pa = c_wchar_p.from_param(c_wchar_p(u"123"))
|
||||||
|
self.failUnlessEqual(type(pa), c_wchar_p)
|
||||||
|
|
||||||
|
def test_int_pointers(self):
|
||||||
|
from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer
|
||||||
|
LPINT = POINTER(c_int)
|
||||||
|
|
||||||
|
## p = pointer(c_int(42))
|
||||||
|
## x = LPINT.from_param(p)
|
||||||
|
x = LPINT.from_param(pointer(c_int(42)))
|
||||||
|
self.failUnlessEqual(x.contents.value, 42)
|
||||||
|
self.failUnlessEqual(LPINT(c_int(42)).contents.value, 42)
|
||||||
|
|
||||||
|
self.failUnlessEqual(LPINT.from_param(None), 0)
|
||||||
|
|
||||||
|
if c_int != c_long:
|
||||||
|
self.assertRaises(TypeError, LPINT.from_param, pointer(c_long(42)))
|
||||||
|
self.assertRaises(TypeError, LPINT.from_param, pointer(c_uint(42)))
|
||||||
|
self.assertRaises(TypeError, LPINT.from_param, pointer(c_short(42)))
|
||||||
|
|
||||||
|
def test_byref_pointer(self):
|
||||||
|
# The from_param class method of POINTER(typ) classes accepts what is
|
||||||
|
# returned by byref(obj), it type(obj) == typ
|
||||||
|
from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
|
||||||
|
LPINT = POINTER(c_int)
|
||||||
|
|
||||||
|
LPINT.from_param(byref(c_int(42)))
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, LPINT.from_param, byref(c_short(22)))
|
||||||
|
if c_int != c_long:
|
||||||
|
self.assertRaises(TypeError, LPINT.from_param, byref(c_long(22)))
|
||||||
|
self.assertRaises(TypeError, LPINT.from_param, byref(c_uint(22)))
|
||||||
|
|
||||||
|
def test_byref_pointerpointer(self):
|
||||||
|
# See above
|
||||||
|
from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
|
||||||
|
|
||||||
|
LPLPINT = POINTER(POINTER(c_int))
|
||||||
|
LPLPINT.from_param(byref(pointer(c_int(42))))
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_short(22))))
|
||||||
|
if c_int != c_long:
|
||||||
|
self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_long(22))))
|
||||||
|
self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_uint(22))))
|
||||||
|
|
||||||
|
def test_array_pointers(self):
|
||||||
|
from ctypes import c_short, c_uint, c_int, c_long, POINTER
|
||||||
|
INTARRAY = c_int * 3
|
||||||
|
ia = INTARRAY()
|
||||||
|
self.failUnlessEqual(len(ia), 3)
|
||||||
|
self.failUnlessEqual([ia[i] for i in range(3)], [0, 0, 0])
|
||||||
|
|
||||||
|
# Pointers are only compatible with arrays containing items of
|
||||||
|
# the same type!
|
||||||
|
LPINT = POINTER(c_int)
|
||||||
|
LPINT.from_param((c_int*3)())
|
||||||
|
self.assertRaises(TypeError, LPINT.from_param, c_short*3)
|
||||||
|
self.assertRaises(TypeError, LPINT.from_param, c_long*3)
|
||||||
|
self.assertRaises(TypeError, LPINT.from_param, c_uint*3)
|
||||||
|
|
||||||
|
## def test_performance(self):
|
||||||
|
## check_perf()
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
171
Lib/ctypes/test/test_pointers.py
Normal file
171
Lib/ctypes/test/test_pointers.py
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from ctypes import *
|
||||||
|
import _ctypes_test
|
||||||
|
|
||||||
|
ctype_types = [c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
|
||||||
|
c_long, c_ulong, c_longlong, c_ulonglong, c_double, c_float]
|
||||||
|
python_types = [int, int, int, int, int, long,
|
||||||
|
int, long, long, long, float, float]
|
||||||
|
|
||||||
|
class PointersTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_pointer_crash(self):
|
||||||
|
|
||||||
|
class A(POINTER(c_ulong)):
|
||||||
|
pass
|
||||||
|
|
||||||
|
POINTER(c_ulong)(c_ulong(22))
|
||||||
|
# Pointer can't set contents: has no _type_
|
||||||
|
self.failUnlessRaises(TypeError, A, c_ulong(33))
|
||||||
|
|
||||||
|
def test_pass_pointers(self):
|
||||||
|
dll = cdll.load(_ctypes_test.__file__)
|
||||||
|
func = dll._testfunc_p_p
|
||||||
|
func.restype = c_long
|
||||||
|
|
||||||
|
i = c_int(12345678)
|
||||||
|
## func.argtypes = (POINTER(c_int),)
|
||||||
|
address = func(byref(i))
|
||||||
|
self.failUnlessEqual(c_int.from_address(address).value, 12345678)
|
||||||
|
|
||||||
|
func.restype = POINTER(c_int)
|
||||||
|
res = func(pointer(i))
|
||||||
|
self.failUnlessEqual(res.contents.value, 12345678)
|
||||||
|
self.failUnlessEqual(res[0], 12345678)
|
||||||
|
|
||||||
|
def test_change_pointers(self):
|
||||||
|
dll = cdll.load(_ctypes_test.__file__)
|
||||||
|
func = dll._testfunc_p_p
|
||||||
|
|
||||||
|
i = c_int(87654)
|
||||||
|
func.restype = POINTER(c_int)
|
||||||
|
func.argtypes = (POINTER(c_int),)
|
||||||
|
|
||||||
|
res = func(pointer(i))
|
||||||
|
self.failUnlessEqual(res[0], 87654)
|
||||||
|
self.failUnlessEqual(res.contents.value, 87654)
|
||||||
|
|
||||||
|
# C code: *res = 54345
|
||||||
|
res[0] = 54345
|
||||||
|
self.failUnlessEqual(i.value, 54345)
|
||||||
|
|
||||||
|
# C code:
|
||||||
|
# int x = 12321;
|
||||||
|
# res = &x
|
||||||
|
res.contents = c_int(12321)
|
||||||
|
self.failUnlessEqual(i.value, 54345)
|
||||||
|
|
||||||
|
def test_callbacks_with_pointers(self):
|
||||||
|
# a function type receiving a pointer
|
||||||
|
PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int))
|
||||||
|
|
||||||
|
self.result = []
|
||||||
|
|
||||||
|
def func(arg):
|
||||||
|
for i in range(10):
|
||||||
|
## print arg[i],
|
||||||
|
self.result.append(arg[i])
|
||||||
|
## print
|
||||||
|
return 0
|
||||||
|
callback = PROTOTYPE(func)
|
||||||
|
|
||||||
|
dll = cdll.load(_ctypes_test.__file__)
|
||||||
|
# This function expects a function pointer,
|
||||||
|
# and calls this with an integer pointer as parameter.
|
||||||
|
# The int pointer points to a table containing the numbers 1..10
|
||||||
|
doit = dll._testfunc_callback_with_pointer
|
||||||
|
|
||||||
|
## i = c_int(42)
|
||||||
|
## callback(byref(i))
|
||||||
|
## self.failUnless(i.value == 84)
|
||||||
|
|
||||||
|
doit(callback)
|
||||||
|
## print self.result
|
||||||
|
doit(callback)
|
||||||
|
## print self.result
|
||||||
|
|
||||||
|
def test_basics(self):
|
||||||
|
from operator import delitem
|
||||||
|
for ct, pt in zip(ctype_types, python_types):
|
||||||
|
i = ct(42)
|
||||||
|
p = pointer(i)
|
||||||
|
## print type(p.contents), ct
|
||||||
|
self.failUnless(type(p.contents) is ct)
|
||||||
|
# p.contents is the same as p[0]
|
||||||
|
## print p.contents
|
||||||
|
## self.failUnless(p.contents == 42)
|
||||||
|
## self.failUnless(p[0] == 42)
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, delitem, p, 0)
|
||||||
|
|
||||||
|
def test_from_address(self):
|
||||||
|
from array import array
|
||||||
|
a = array('i', [100, 200, 300, 400, 500])
|
||||||
|
addr = a.buffer_info()[0]
|
||||||
|
|
||||||
|
p = POINTER(POINTER(c_int))
|
||||||
|
## print dir(p)
|
||||||
|
## print p.from_address
|
||||||
|
## print p.from_address(addr)[0][0]
|
||||||
|
|
||||||
|
def test_other(self):
|
||||||
|
class Table(Structure):
|
||||||
|
_fields_ = [("a", c_int),
|
||||||
|
("b", c_int),
|
||||||
|
("c", c_int)]
|
||||||
|
|
||||||
|
pt = pointer(Table(1, 2, 3))
|
||||||
|
|
||||||
|
self.failUnlessEqual(pt.contents.a, 1)
|
||||||
|
self.failUnlessEqual(pt.contents.b, 2)
|
||||||
|
self.failUnlessEqual(pt.contents.c, 3)
|
||||||
|
|
||||||
|
pt.contents.c = 33
|
||||||
|
|
||||||
|
from ctypes import _pointer_type_cache
|
||||||
|
del _pointer_type_cache[Table]
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
p = pointer(c_int(42))
|
||||||
|
# Although a pointer can be indexed, it ha no length
|
||||||
|
self.assertRaises(TypeError, len, p)
|
||||||
|
self.failUnlessEqual(p[0], 42)
|
||||||
|
self.failUnlessEqual(p.contents.value, 42)
|
||||||
|
|
||||||
|
def test_incomplete(self):
|
||||||
|
lpcell = POINTER("cell")
|
||||||
|
class cell(Structure):
|
||||||
|
_fields_ = [("value", c_int),
|
||||||
|
("next", lpcell)]
|
||||||
|
SetPointerType(lpcell, cell)
|
||||||
|
|
||||||
|
# Make a structure containing a pointer to itself:
|
||||||
|
c = cell()
|
||||||
|
c.value = 42
|
||||||
|
c.next = pointer(c)
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for i in range(8):
|
||||||
|
result.append(c.value)
|
||||||
|
c = c.next[0]
|
||||||
|
self.failUnlessEqual(result, [42] * 8)
|
||||||
|
|
||||||
|
from ctypes import _pointer_type_cache
|
||||||
|
del _pointer_type_cache[cell]
|
||||||
|
|
||||||
|
def test_charpp( self ):
|
||||||
|
"""Test that a character pointer-to-pointer is correctly passed"""
|
||||||
|
dll = cdll.load(_ctypes_test.__file__)
|
||||||
|
func = dll._testfunc_c_p_p
|
||||||
|
func.restype = c_char_p
|
||||||
|
argv = (c_char_p * 2)()
|
||||||
|
argc = c_int( 2 )
|
||||||
|
argv[0] = 'hello'
|
||||||
|
argv[1] = 'world'
|
||||||
|
result = func( byref(argc), argv )
|
||||||
|
assert result == 'world', result
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
38
Lib/ctypes/test/test_posix.py
Normal file
38
Lib/ctypes/test/test_posix.py
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
import unittest, os, sys
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
if os.name == "posix" and sys.platform == "linux2":
|
||||||
|
# I don't really know on which platforms this works,
|
||||||
|
# later it should use the find_library stuff to avoid
|
||||||
|
# hardcoding the names.
|
||||||
|
|
||||||
|
class TestRTLD_GLOBAL(unittest.TestCase):
|
||||||
|
def test_GL(self):
|
||||||
|
cdll.load('libGL.so', mode=RTLD_GLOBAL)
|
||||||
|
cdll.load('libGLU.so')
|
||||||
|
|
||||||
|
##if os.name == "posix" and sys.platform != "darwin":
|
||||||
|
|
||||||
|
## # On platforms where the default shared library suffix is '.so',
|
||||||
|
## # at least some libraries can be loaded as attributes of the cdll
|
||||||
|
## # object, since ctypes now tries loading the lib again
|
||||||
|
## # with '.so' appended of the first try fails.
|
||||||
|
## #
|
||||||
|
## # Won't work for libc, unfortunately. OTOH, it isn't
|
||||||
|
## # needed for libc since this is already mapped into the current
|
||||||
|
## # process (?)
|
||||||
|
## #
|
||||||
|
## # On MAC OSX, it won't work either, because dlopen() needs a full path,
|
||||||
|
## # and the default suffix is either none or '.dylib'.
|
||||||
|
|
||||||
|
## class LoadLibs(unittest.TestCase):
|
||||||
|
## def test_libm(self):
|
||||||
|
## import math
|
||||||
|
## libm = cdll.libm
|
||||||
|
## sqrt = libm.sqrt
|
||||||
|
## sqrt.argtypes = (c_double,)
|
||||||
|
## sqrt.restype = c_double
|
||||||
|
## self.failUnlessEqual(sqrt(2), math.sqrt(2))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
184
Lib/ctypes/test/test_prototypes.py
Normal file
184
Lib/ctypes/test/test_prototypes.py
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
from ctypes import *
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
# IMPORTANT INFO:
|
||||||
|
#
|
||||||
|
# Consider this call:
|
||||||
|
# func.restype = c_char_p
|
||||||
|
# func(c_char_p("123"))
|
||||||
|
# It returns
|
||||||
|
# "123"
|
||||||
|
#
|
||||||
|
# WHY IS THIS SO?
|
||||||
|
#
|
||||||
|
# argument tuple (c_char_p("123"), ) is destroyed after the function
|
||||||
|
# func is called, but NOT before the result is actually built.
|
||||||
|
#
|
||||||
|
# If the arglist would be destroyed BEFORE the result has been built,
|
||||||
|
# the c_char_p("123") object would already have a zero refcount,
|
||||||
|
# and the pointer passed to (and returned by) the function would
|
||||||
|
# probably point to deallocated space.
|
||||||
|
#
|
||||||
|
# In this case, there would have to be an additional reference to the argument...
|
||||||
|
|
||||||
|
import _ctypes_test
|
||||||
|
testdll = cdll.load(_ctypes_test.__file__)
|
||||||
|
|
||||||
|
def c_wbuffer(init):
|
||||||
|
n = len(init) + 1
|
||||||
|
return (c_wchar * n)(*init)
|
||||||
|
|
||||||
|
class CharPointersTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
func = testdll._testfunc_p_p
|
||||||
|
func.restype = c_long
|
||||||
|
func.argtypes = None
|
||||||
|
|
||||||
|
def test_int_pointer_arg(self):
|
||||||
|
func = testdll._testfunc_p_p
|
||||||
|
func.restype = c_long
|
||||||
|
self.failUnlessEqual(0, func(0))
|
||||||
|
|
||||||
|
ci = c_int(0)
|
||||||
|
|
||||||
|
func.argtypes = POINTER(c_int),
|
||||||
|
self.failUnlessEqual(addressof(ci), func(byref(ci)))
|
||||||
|
|
||||||
|
func.argtypes = c_char_p,
|
||||||
|
self.assertRaises(ArgumentError, func, byref(ci))
|
||||||
|
|
||||||
|
func.argtypes = POINTER(c_short),
|
||||||
|
self.assertRaises(ArgumentError, func, byref(ci))
|
||||||
|
|
||||||
|
func.argtypes = POINTER(c_double),
|
||||||
|
self.assertRaises(ArgumentError, func, byref(ci))
|
||||||
|
|
||||||
|
def test_POINTER_c_char_arg(self):
|
||||||
|
func = testdll._testfunc_p_p
|
||||||
|
func.restype = c_char_p
|
||||||
|
func.argtypes = POINTER(c_char),
|
||||||
|
|
||||||
|
self.failUnlessEqual(None, func(None))
|
||||||
|
self.failUnlessEqual("123", func("123"))
|
||||||
|
self.failUnlessEqual(None, func(c_char_p(None)))
|
||||||
|
self.failUnlessEqual("123", func(c_char_p("123")))
|
||||||
|
|
||||||
|
self.failUnlessEqual("123", func(c_buffer("123")))
|
||||||
|
ca = c_char("a")
|
||||||
|
self.failUnlessEqual("a", func(pointer(ca))[0])
|
||||||
|
self.failUnlessEqual("a", func(byref(ca))[0])
|
||||||
|
|
||||||
|
def test_c_char_p_arg(self):
|
||||||
|
func = testdll._testfunc_p_p
|
||||||
|
func.restype = c_char_p
|
||||||
|
func.argtypes = c_char_p,
|
||||||
|
|
||||||
|
self.failUnlessEqual(None, func(None))
|
||||||
|
self.failUnlessEqual("123", func("123"))
|
||||||
|
self.failUnlessEqual(None, func(c_char_p(None)))
|
||||||
|
self.failUnlessEqual("123", func(c_char_p("123")))
|
||||||
|
|
||||||
|
self.failUnlessEqual("123", func(c_buffer("123")))
|
||||||
|
ca = c_char("a")
|
||||||
|
self.failUnlessEqual("a", func(pointer(ca))[0])
|
||||||
|
self.failUnlessEqual("a", func(byref(ca))[0])
|
||||||
|
|
||||||
|
def test_c_void_p_arg(self):
|
||||||
|
func = testdll._testfunc_p_p
|
||||||
|
func.restype = c_char_p
|
||||||
|
func.argtypes = c_void_p,
|
||||||
|
|
||||||
|
self.failUnlessEqual(None, func(None))
|
||||||
|
self.failUnlessEqual("123", func("123"))
|
||||||
|
self.failUnlessEqual("123", func(c_char_p("123")))
|
||||||
|
self.failUnlessEqual(None, func(c_char_p(None)))
|
||||||
|
|
||||||
|
self.failUnlessEqual("123", func(c_buffer("123")))
|
||||||
|
ca = c_char("a")
|
||||||
|
self.failUnlessEqual("a", func(pointer(ca))[0])
|
||||||
|
self.failUnlessEqual("a", func(byref(ca))[0])
|
||||||
|
|
||||||
|
func(byref(c_int()))
|
||||||
|
func(pointer(c_int()))
|
||||||
|
func((c_int * 3)())
|
||||||
|
|
||||||
|
try:
|
||||||
|
func.restype = c_wchar_p
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.failUnlessEqual(None, func(c_wchar_p(None)))
|
||||||
|
self.failUnlessEqual(u"123", func(c_wchar_p(u"123")))
|
||||||
|
|
||||||
|
## def test_instance(self):
|
||||||
|
## func = testdll._testfunc_p_p
|
||||||
|
|
||||||
|
## class X:
|
||||||
|
## _as_parameter_ = 0
|
||||||
|
|
||||||
|
## self.failUnlessEqual(0, func(X()))
|
||||||
|
|
||||||
|
try:
|
||||||
|
c_wchar
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
class WCharPointersTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
func = testdll._testfunc_p_p
|
||||||
|
func.restype = c_int
|
||||||
|
func.argtypes = None
|
||||||
|
|
||||||
|
|
||||||
|
def test_POINTER_c_wchar_arg(self):
|
||||||
|
func = testdll._testfunc_p_p
|
||||||
|
func.restype = c_wchar_p
|
||||||
|
func.argtypes = POINTER(c_wchar),
|
||||||
|
|
||||||
|
self.failUnlessEqual(None, func(None))
|
||||||
|
self.failUnlessEqual(u"123", func(u"123"))
|
||||||
|
self.failUnlessEqual(None, func(c_wchar_p(None)))
|
||||||
|
self.failUnlessEqual(u"123", func(c_wchar_p(u"123")))
|
||||||
|
|
||||||
|
self.failUnlessEqual(u"123", func(c_wbuffer(u"123")))
|
||||||
|
ca = c_wchar("a")
|
||||||
|
self.failUnlessEqual(u"a", func(pointer(ca))[0])
|
||||||
|
self.failUnlessEqual(u"a", func(byref(ca))[0])
|
||||||
|
|
||||||
|
def test_c_wchar_p_arg(self):
|
||||||
|
func = testdll._testfunc_p_p
|
||||||
|
func.restype = c_wchar_p
|
||||||
|
func.argtypes = c_wchar_p,
|
||||||
|
|
||||||
|
c_wchar_p.from_param(u"123")
|
||||||
|
|
||||||
|
self.failUnlessEqual(None, func(None))
|
||||||
|
self.failUnlessEqual("123", func(u"123"))
|
||||||
|
self.failUnlessEqual(None, func(c_wchar_p(None)))
|
||||||
|
self.failUnlessEqual("123", func(c_wchar_p("123")))
|
||||||
|
|
||||||
|
# XXX Currently, these raise TypeErrors, although they shouldn't:
|
||||||
|
self.failUnlessEqual("123", func(c_wbuffer("123")))
|
||||||
|
ca = c_wchar("a")
|
||||||
|
self.failUnlessEqual("a", func(pointer(ca))[0])
|
||||||
|
self.failUnlessEqual("a", func(byref(ca))[0])
|
||||||
|
|
||||||
|
class ArrayTest(unittest.TestCase):
|
||||||
|
def test(self):
|
||||||
|
func = testdll._testfunc_ai8
|
||||||
|
func.restype = POINTER(c_int)
|
||||||
|
func.argtypes = c_int * 8,
|
||||||
|
|
||||||
|
func((c_int * 8)(1, 2, 3, 4, 5, 6, 7, 8))
|
||||||
|
|
||||||
|
# This did crash before:
|
||||||
|
|
||||||
|
def func(): pass
|
||||||
|
CFUNCTYPE(None, c_int * 3)(func)
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
77
Lib/ctypes/test/test_python_api.py
Normal file
77
Lib/ctypes/test/test_python_api.py
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
from ctypes import *
|
||||||
|
import unittest, sys
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
# This section should be moved into ctypes\__init__.py, when it's ready.
|
||||||
|
|
||||||
|
from _ctypes import PyObj_FromPtr
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
from sys import getrefcount as grc
|
||||||
|
|
||||||
|
|
||||||
|
class PythonAPITestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_PyString_FromStringAndSize(self):
|
||||||
|
PyString_FromStringAndSize = pythonapi.PyString_FromStringAndSize
|
||||||
|
|
||||||
|
PyString_FromStringAndSize.restype = py_object
|
||||||
|
PyString_FromStringAndSize.argtypes = c_char_p, c_int
|
||||||
|
|
||||||
|
self.failUnlessEqual(PyString_FromStringAndSize("abcdefghi", 3), "abc")
|
||||||
|
|
||||||
|
def test_PyString_FromString(self):
|
||||||
|
pythonapi.PyString_FromString.restype = py_object
|
||||||
|
pythonapi.PyString_FromString.argtypes = (c_char_p,)
|
||||||
|
|
||||||
|
s = "abc"
|
||||||
|
refcnt = grc(s)
|
||||||
|
pyob = pythonapi.PyString_FromString(s)
|
||||||
|
self.failUnlessEqual(grc(s), refcnt)
|
||||||
|
self.failUnlessEqual(s, pyob)
|
||||||
|
del pyob
|
||||||
|
self.failUnlessEqual(grc(s), refcnt)
|
||||||
|
|
||||||
|
def test_PyInt_Long(self):
|
||||||
|
ref42 = grc(42)
|
||||||
|
pythonapi.PyInt_FromLong.restype = py_object
|
||||||
|
self.failUnlessEqual(pythonapi.PyInt_FromLong(42), 42)
|
||||||
|
|
||||||
|
self.failUnlessEqual(grc(42), ref42)
|
||||||
|
|
||||||
|
pythonapi.PyInt_AsLong.argtypes = (py_object,)
|
||||||
|
pythonapi.PyInt_AsLong.restype = c_long
|
||||||
|
|
||||||
|
res = pythonapi.PyInt_AsLong(42)
|
||||||
|
self.failUnlessEqual(grc(res), ref42 + 1)
|
||||||
|
del res
|
||||||
|
self.failUnlessEqual(grc(42), ref42)
|
||||||
|
|
||||||
|
def test_PyObj_FromPtr(self):
|
||||||
|
s = "abc def ghi jkl"
|
||||||
|
ref = grc(s)
|
||||||
|
# id(python-object) is the address
|
||||||
|
pyobj = PyObj_FromPtr(id(s))
|
||||||
|
self.failUnless(s is pyobj)
|
||||||
|
|
||||||
|
self.failUnlessEqual(grc(s), ref + 1)
|
||||||
|
del pyobj
|
||||||
|
self.failUnlessEqual(grc(s), ref)
|
||||||
|
|
||||||
|
def test_PyOS_snprintf(self):
|
||||||
|
PyOS_snprintf = pythonapi.PyOS_snprintf
|
||||||
|
PyOS_snprintf.argtypes = POINTER(c_char), c_int, c_char_p
|
||||||
|
|
||||||
|
buf = c_buffer(256)
|
||||||
|
PyOS_snprintf(buf, sizeof(buf), "Hello from %s", "ctypes")
|
||||||
|
self.failUnlessEqual(buf.value, "Hello from ctypes")
|
||||||
|
|
||||||
|
PyOS_snprintf(buf, sizeof(buf), "Hello from %s", "ctypes", 1, 2, 3)
|
||||||
|
self.failUnlessEqual(buf.value, "Hello from ctypes")
|
||||||
|
|
||||||
|
# not enough arguments
|
||||||
|
self.failUnlessRaises(TypeError, PyOS_snprintf, buf)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
73
Lib/ctypes/test/test_random_things.py
Normal file
73
Lib/ctypes/test/test_random_things.py
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
from ctypes import *
|
||||||
|
import unittest, sys
|
||||||
|
|
||||||
|
def callback_func(arg):
|
||||||
|
42 / arg
|
||||||
|
raise ValueError, arg
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
|
||||||
|
class call_function_TestCase(unittest.TestCase):
|
||||||
|
# _ctypes.call_function is deprecated and private, but used by
|
||||||
|
# Gary Bishp's readline module. If we have it, we must test it as well.
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
from _ctypes import call_function
|
||||||
|
hdll = windll.kernel32.LoadLibraryA("kernel32")
|
||||||
|
funcaddr = windll.kernel32.GetProcAddress(hdll, "GetModuleHandleA")
|
||||||
|
|
||||||
|
self.failUnlessEqual(call_function(funcaddr, (None,)),
|
||||||
|
windll.kernel32.GetModuleHandleA(None))
|
||||||
|
|
||||||
|
class CallbackTracbackTestCase(unittest.TestCase):
|
||||||
|
# When an exception is raised in a ctypes callback function, the C
|
||||||
|
# code prints a traceback.
|
||||||
|
#
|
||||||
|
# This test makes sure the exception types *and* the exception
|
||||||
|
# value is printed correctly.
|
||||||
|
#
|
||||||
|
# Changed in 0.9.3: No longer is '(in callback)' prepended to the
|
||||||
|
# error message - instead a additional frame for the C code is
|
||||||
|
# created, then a full traceback printed. When SystemExit is
|
||||||
|
# raised in a callback function, the interpreter exits.
|
||||||
|
|
||||||
|
def capture_stderr(self, func, *args, **kw):
|
||||||
|
# helper - call function 'func', and return the captured stderr
|
||||||
|
import StringIO
|
||||||
|
old_stderr = sys.stderr
|
||||||
|
logger = sys.stderr = StringIO.StringIO()
|
||||||
|
try:
|
||||||
|
func(*args, **kw)
|
||||||
|
finally:
|
||||||
|
sys.stderr = old_stderr
|
||||||
|
return logger.getvalue()
|
||||||
|
|
||||||
|
def test_ValueError(self):
|
||||||
|
cb = CFUNCTYPE(c_int, c_int)(callback_func)
|
||||||
|
out = self.capture_stderr(cb, 42)
|
||||||
|
self.failUnlessEqual(out.splitlines()[-1],
|
||||||
|
"ValueError: 42")
|
||||||
|
|
||||||
|
def test_IntegerDivisionError(self):
|
||||||
|
cb = CFUNCTYPE(c_int, c_int)(callback_func)
|
||||||
|
out = self.capture_stderr(cb, 0)
|
||||||
|
self.failUnlessEqual(out.splitlines()[-1],
|
||||||
|
"ZeroDivisionError: "
|
||||||
|
"integer division or modulo by zero")
|
||||||
|
|
||||||
|
def test_FloatDivisionError(self):
|
||||||
|
cb = CFUNCTYPE(c_int, c_double)(callback_func)
|
||||||
|
out = self.capture_stderr(cb, 0.0)
|
||||||
|
self.failUnlessEqual(out.splitlines()[-1],
|
||||||
|
"ZeroDivisionError: "
|
||||||
|
"float division")
|
||||||
|
|
||||||
|
def test_TypeErrorDivisionError(self):
|
||||||
|
cb = CFUNCTYPE(c_int, c_char_p)(callback_func)
|
||||||
|
out = self.capture_stderr(cb, "spam")
|
||||||
|
self.failUnlessEqual(out.splitlines()[-1],
|
||||||
|
"TypeError: "
|
||||||
|
"unsupported operand type(s) for /: 'int' and 'str'")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
98
Lib/ctypes/test/test_refcounts.py
Normal file
98
Lib/ctypes/test/test_refcounts.py
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
import unittest
|
||||||
|
import ctypes
|
||||||
|
import gc
|
||||||
|
|
||||||
|
MyCallback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int)
|
||||||
|
OtherCallback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_ulonglong)
|
||||||
|
|
||||||
|
import _ctypes_test
|
||||||
|
dll = ctypes.cdll.load(_ctypes_test.__file__)
|
||||||
|
|
||||||
|
class RefcountTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_1(self):
|
||||||
|
from sys import getrefcount as grc
|
||||||
|
|
||||||
|
f = dll._testfunc_callback_i_if
|
||||||
|
f.restype = ctypes.c_int
|
||||||
|
f.argtypes = [ctypes.c_int, MyCallback]
|
||||||
|
|
||||||
|
def callback(value):
|
||||||
|
#print "called back with", value
|
||||||
|
return value
|
||||||
|
|
||||||
|
self.failUnlessEqual(grc(callback), 2)
|
||||||
|
cb = MyCallback(callback)
|
||||||
|
|
||||||
|
self.failUnless(grc(callback) > 2)
|
||||||
|
result = f(-10, cb)
|
||||||
|
self.failUnlessEqual(result, -18)
|
||||||
|
cb = None
|
||||||
|
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
self.failUnlessEqual(grc(callback), 2)
|
||||||
|
|
||||||
|
|
||||||
|
def test_refcount(self):
|
||||||
|
from sys import getrefcount as grc
|
||||||
|
def func(*args):
|
||||||
|
pass
|
||||||
|
# this is the standard refcount for func
|
||||||
|
self.failUnlessEqual(grc(func), 2)
|
||||||
|
|
||||||
|
# the CFuncPtr instance holds atr least one refcount on func:
|
||||||
|
f = OtherCallback(func)
|
||||||
|
self.failUnless(grc(func) > 2)
|
||||||
|
|
||||||
|
# and may release it again
|
||||||
|
del f
|
||||||
|
self.failUnless(grc(func) >= 2)
|
||||||
|
|
||||||
|
# but now it must be gone
|
||||||
|
gc.collect()
|
||||||
|
self.failUnless(grc(func) == 2)
|
||||||
|
|
||||||
|
class X(ctypes.Structure):
|
||||||
|
_fields_ = [("a", OtherCallback)]
|
||||||
|
x = X()
|
||||||
|
x.a = OtherCallback(func)
|
||||||
|
|
||||||
|
# the CFuncPtr instance holds atr least one refcount on func:
|
||||||
|
self.failUnless(grc(func) > 2)
|
||||||
|
|
||||||
|
# and may release it again
|
||||||
|
del x
|
||||||
|
self.failUnless(grc(func) >= 2)
|
||||||
|
|
||||||
|
# and now it must be gone again
|
||||||
|
gc.collect()
|
||||||
|
self.failUnlessEqual(grc(func), 2)
|
||||||
|
|
||||||
|
f = OtherCallback(func)
|
||||||
|
|
||||||
|
# the CFuncPtr instance holds atr least one refcount on func:
|
||||||
|
self.failUnless(grc(func) > 2)
|
||||||
|
|
||||||
|
# create a cycle
|
||||||
|
f.cycle = f
|
||||||
|
|
||||||
|
del f
|
||||||
|
gc.collect()
|
||||||
|
self.failUnlessEqual(grc(func), 2)
|
||||||
|
|
||||||
|
class AnotherLeak(unittest.TestCase):
|
||||||
|
def test_callback(self):
|
||||||
|
import sys
|
||||||
|
|
||||||
|
proto = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int)
|
||||||
|
def func(a, b):
|
||||||
|
return a * b * 2
|
||||||
|
f = proto(func)
|
||||||
|
|
||||||
|
a = sys.getrefcount(ctypes.c_int)
|
||||||
|
f(1, 2)
|
||||||
|
self.failUnlessEqual(sys.getrefcount(ctypes.c_int), a)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
24
Lib/ctypes/test/test_repr.py
Normal file
24
Lib/ctypes/test/test_repr.py
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
from ctypes import *
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
nums = [c_byte, c_short, c_int, c_long, c_longlong,
|
||||||
|
c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong,
|
||||||
|
c_float, c_double]
|
||||||
|
|
||||||
|
class ReprTest(unittest.TestCase):
|
||||||
|
def test_numbers(self):
|
||||||
|
for typ in nums:
|
||||||
|
self.failUnless(repr(typ(42)).startswith(typ.__name__))
|
||||||
|
class X(typ):
|
||||||
|
pass
|
||||||
|
self.failUnlessEqual("<X object at", repr(X(42))[:12])
|
||||||
|
|
||||||
|
def test_char(self):
|
||||||
|
self.failUnlessEqual("c_char('x')", repr(c_char('x')))
|
||||||
|
|
||||||
|
class X(c_char):
|
||||||
|
pass
|
||||||
|
self.failUnlessEqual("<X object at", repr(X('x'))[:12])
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
35
Lib/ctypes/test/test_returnfuncptrs.py
Normal file
35
Lib/ctypes/test/test_returnfuncptrs.py
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
import _ctypes_test
|
||||||
|
|
||||||
|
class ReturnFuncPtrTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_with_prototype(self):
|
||||||
|
# The _ctypes_test shared lib/dll exports quite some functions for testing.
|
||||||
|
# The get_strchr function returns a *pointer* to the C strchr function.
|
||||||
|
dll = cdll.load(_ctypes_test.__file__)
|
||||||
|
get_strchr = dll.get_strchr
|
||||||
|
get_strchr.restype = CFUNCTYPE(c_char_p, c_char_p, c_char)
|
||||||
|
strchr = get_strchr()
|
||||||
|
self.failUnlessEqual(strchr("abcdef", "b"), "bcdef")
|
||||||
|
self.failUnlessEqual(strchr("abcdef", "x"), None)
|
||||||
|
self.assertRaises(ArgumentError, strchr, "abcdef", 3)
|
||||||
|
self.assertRaises(TypeError, strchr, "abcdef")
|
||||||
|
|
||||||
|
def test_without_prototype(self):
|
||||||
|
dll = cdll.load(_ctypes_test.__file__)
|
||||||
|
get_strchr = dll.get_strchr
|
||||||
|
# the default 'c_int' would not work on systems where sizeof(int) != sizeof(void *)
|
||||||
|
get_strchr.restype = c_void_p
|
||||||
|
addr = get_strchr()
|
||||||
|
# _CFuncPtr instances are now callable with an integer argument
|
||||||
|
# which denotes a function address:
|
||||||
|
strchr = CFUNCTYPE(c_char_p, c_char_p, c_char)(addr)
|
||||||
|
self.failUnless(strchr("abcdef", "b"), "bcdef")
|
||||||
|
self.failUnlessEqual(strchr("abcdef", "x"), None)
|
||||||
|
self.assertRaises(ArgumentError, strchr, "abcdef", 3)
|
||||||
|
self.assertRaises(TypeError, strchr, "abcdef")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
55
Lib/ctypes/test/test_simplesubclasses.py
Normal file
55
Lib/ctypes/test/test_simplesubclasses.py
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
class MyInt(c_int):
|
||||||
|
def __cmp__(self, other):
|
||||||
|
if type(other) != MyInt:
|
||||||
|
return -1
|
||||||
|
return cmp(self.value, other.value)
|
||||||
|
|
||||||
|
class Test(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_compare(self):
|
||||||
|
self.failUnlessEqual(MyInt(3), MyInt(3))
|
||||||
|
self.failIfEqual(MyInt(42), MyInt(43))
|
||||||
|
|
||||||
|
def test_ignore_retval(self):
|
||||||
|
# Test if the return value of a callback is ignored
|
||||||
|
# if restype is None
|
||||||
|
proto = CFUNCTYPE(None)
|
||||||
|
def func():
|
||||||
|
return (1, "abc", None)
|
||||||
|
|
||||||
|
cb = proto(func)
|
||||||
|
self.failUnlessEqual(None, cb())
|
||||||
|
|
||||||
|
|
||||||
|
def test_int_callback(self):
|
||||||
|
args = []
|
||||||
|
def func(arg):
|
||||||
|
args.append(arg)
|
||||||
|
return arg
|
||||||
|
|
||||||
|
cb = CFUNCTYPE(None, MyInt)(func)
|
||||||
|
|
||||||
|
self.failUnlessEqual(None, cb(42))
|
||||||
|
self.failUnlessEqual(type(args[-1]), MyInt)
|
||||||
|
|
||||||
|
cb = CFUNCTYPE(c_int, c_int)(func)
|
||||||
|
|
||||||
|
self.failUnlessEqual(42, cb(42))
|
||||||
|
self.failUnlessEqual(type(args[-1]), int)
|
||||||
|
|
||||||
|
def test_int_struct(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("x", MyInt)]
|
||||||
|
|
||||||
|
self.failUnlessEqual(X().x, MyInt())
|
||||||
|
|
||||||
|
s = X()
|
||||||
|
s.x = MyInt(42)
|
||||||
|
|
||||||
|
self.failUnlessEqual(s.x, MyInt(42))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
24
Lib/ctypes/test/test_sizes.py
Normal file
24
Lib/ctypes/test/test_sizes.py
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Test specifically-sized containers.
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
class SizesTestCase(unittest.TestCase):
|
||||||
|
def test_8(self):
|
||||||
|
self.failUnlessEqual(1, sizeof(c_int8))
|
||||||
|
self.failUnlessEqual(1, sizeof(c_uint8))
|
||||||
|
|
||||||
|
def test_16(self):
|
||||||
|
self.failUnlessEqual(2, sizeof(c_int16))
|
||||||
|
self.failUnlessEqual(2, sizeof(c_uint16))
|
||||||
|
|
||||||
|
def test_32(self):
|
||||||
|
self.failUnlessEqual(4, sizeof(c_int32))
|
||||||
|
self.failUnlessEqual(4, sizeof(c_uint32))
|
||||||
|
|
||||||
|
def test_64(self):
|
||||||
|
self.failUnlessEqual(8, sizeof(c_int64))
|
||||||
|
self.failUnlessEqual(8, sizeof(c_uint64))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
90
Lib/ctypes/test/test_slicing.py
Normal file
90
Lib/ctypes/test/test_slicing.py
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
import _ctypes_test
|
||||||
|
|
||||||
|
class SlicesTestCase(unittest.TestCase):
|
||||||
|
def test_getslice_cint(self):
|
||||||
|
a = (c_int * 100)(*xrange(1100, 1200))
|
||||||
|
b = range(1100, 1200)
|
||||||
|
self.failUnlessEqual(a[0:2], b[0:2])
|
||||||
|
self.failUnlessEqual(len(a), len(b))
|
||||||
|
self.failUnlessEqual(a[5:7], b[5:7])
|
||||||
|
self.failUnlessEqual(a[-1], b[-1])
|
||||||
|
self.failUnlessEqual(a[:], b[:])
|
||||||
|
|
||||||
|
a[0:5] = range(5, 10)
|
||||||
|
self.failUnlessEqual(a[0:5], range(5, 10))
|
||||||
|
|
||||||
|
def test_setslice_cint(self):
|
||||||
|
a = (c_int * 100)(*xrange(1100, 1200))
|
||||||
|
b = range(1100, 1200)
|
||||||
|
|
||||||
|
a[32:47] = range(32, 47)
|
||||||
|
self.failUnlessEqual(a[32:47], range(32, 47))
|
||||||
|
|
||||||
|
from operator import setslice
|
||||||
|
|
||||||
|
# TypeError: int expected instead of str instance
|
||||||
|
self.assertRaises(TypeError, setslice, a, 0, 5, "abcde")
|
||||||
|
# TypeError: int expected instead of str instance
|
||||||
|
self.assertRaises(TypeError, setslice, a, 0, 5, ["a", "b", "c", "d", "e"])
|
||||||
|
# TypeError: int expected instead of float instance
|
||||||
|
self.assertRaises(TypeError, setslice, a, 0, 5, [1, 2, 3, 4, 3.14])
|
||||||
|
# ValueError: Can only assign sequence of same size
|
||||||
|
self.assertRaises(ValueError, setslice, a, 0, 5, range(32))
|
||||||
|
|
||||||
|
def test_char_ptr(self):
|
||||||
|
s = "abcdefghijklmnopqrstuvwxyz\0"
|
||||||
|
|
||||||
|
dll = cdll.load(_ctypes_test.__file__)
|
||||||
|
dll.my_strdup.restype = POINTER(c_char)
|
||||||
|
res = dll.my_strdup(s)
|
||||||
|
self.failUnlessEqual(res[:len(s)], s)
|
||||||
|
|
||||||
|
import operator
|
||||||
|
self.assertRaises(TypeError, operator.setslice,
|
||||||
|
res, 0, 5, u"abcde")
|
||||||
|
|
||||||
|
dll.my_strdup.restype = POINTER(c_byte)
|
||||||
|
res = dll.my_strdup(s)
|
||||||
|
self.failUnlessEqual(res[:len(s)-1], range(ord("a"), ord("z")+1))
|
||||||
|
|
||||||
|
def test_char_array(self):
|
||||||
|
s = "abcdefghijklmnopqrstuvwxyz\0"
|
||||||
|
|
||||||
|
p = (c_char * 27)(*s)
|
||||||
|
self.failUnlessEqual(p[:], s)
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
c_wchar
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
def test_wchar_ptr(self):
|
||||||
|
s = u"abcdefghijklmnopqrstuvwxyz\0"
|
||||||
|
|
||||||
|
dll = cdll.load(_ctypes_test.__file__)
|
||||||
|
dll.my_wcsdup.restype = POINTER(c_wchar)
|
||||||
|
dll.my_wcsdup.argtypes = POINTER(c_wchar),
|
||||||
|
res = dll.my_wcsdup(s)
|
||||||
|
self.failUnlessEqual(res[:len(s)], s)
|
||||||
|
|
||||||
|
import operator
|
||||||
|
self.assertRaises(TypeError, operator.setslice,
|
||||||
|
res, 0, 5, u"abcde")
|
||||||
|
|
||||||
|
if sizeof(c_wchar) == sizeof(c_short):
|
||||||
|
dll.my_wcsdup.restype = POINTER(c_short)
|
||||||
|
elif sizeof(c_wchar) == sizeof(c_int):
|
||||||
|
dll.my_wcsdup.restype = POINTER(c_int)
|
||||||
|
elif sizeof(c_wchar) == sizeof(c_long):
|
||||||
|
dll.my_wcsdup.restype = POINTER(c_long)
|
||||||
|
res = dll.my_wcsdup(s)
|
||||||
|
self.failUnlessEqual(res[:len(s)-1], range(ord("a"), ord("z")+1))
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
75
Lib/ctypes/test/test_stringptr.py
Normal file
75
Lib/ctypes/test/test_stringptr.py
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
import _ctypes_test
|
||||||
|
|
||||||
|
lib = cdll.load(_ctypes_test.__file__)
|
||||||
|
|
||||||
|
class StringPtrTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test__POINTER_c_char(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("str", POINTER(c_char))]
|
||||||
|
x = X()
|
||||||
|
|
||||||
|
# NULL pointer access
|
||||||
|
self.assertRaises(ValueError, getattr, x.str, "contents")
|
||||||
|
b = c_buffer("Hello, World")
|
||||||
|
from sys import getrefcount as grc
|
||||||
|
self.failUnlessEqual(grc(b), 2)
|
||||||
|
x.str = b
|
||||||
|
self.failUnlessEqual(grc(b), 3)
|
||||||
|
|
||||||
|
# POINTER(c_char) and Python string is NOT compatible
|
||||||
|
# POINTER(c_char) and c_buffer() is compatible
|
||||||
|
for i in range(len(b)):
|
||||||
|
self.failUnlessEqual(b[i], x.str[i])
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, setattr, x, "str", "Hello, World")
|
||||||
|
|
||||||
|
def test__c_char_p(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("str", c_char_p)]
|
||||||
|
x = X()
|
||||||
|
|
||||||
|
# c_char_p and Python string is compatible
|
||||||
|
# c_char_p and c_buffer is NOT compatible
|
||||||
|
self.failUnlessEqual(x.str, None)
|
||||||
|
x.str = "Hello, World"
|
||||||
|
self.failUnlessEqual(x.str, "Hello, World")
|
||||||
|
b = c_buffer("Hello, World")
|
||||||
|
self.failUnlessRaises(TypeError, setattr, x, "str", b)
|
||||||
|
|
||||||
|
|
||||||
|
def test_functions(self):
|
||||||
|
strchr = lib.my_strchr
|
||||||
|
strchr.restype = c_char_p
|
||||||
|
|
||||||
|
# c_char_p and Python string is compatible
|
||||||
|
# c_char_p and c_buffer are now compatible
|
||||||
|
strchr.argtypes = c_char_p, c_char
|
||||||
|
self.failUnlessEqual(strchr("abcdef", "c"), "cdef")
|
||||||
|
self.failUnlessEqual(strchr(c_buffer("abcdef"), "c"), "cdef")
|
||||||
|
|
||||||
|
# POINTER(c_char) and Python string is NOT compatible
|
||||||
|
# POINTER(c_char) and c_buffer() is compatible
|
||||||
|
strchr.argtypes = POINTER(c_char), c_char
|
||||||
|
buf = c_buffer("abcdef")
|
||||||
|
self.failUnlessEqual(strchr(buf, "c"), "cdef")
|
||||||
|
self.failUnlessEqual(strchr("abcdef", "c"), "cdef")
|
||||||
|
|
||||||
|
# XXX These calls are dangerous, because the first argument
|
||||||
|
# to strchr is no longer valid after the function returns!
|
||||||
|
# So we must keep a reference to buf separately
|
||||||
|
|
||||||
|
strchr.restype = POINTER(c_char)
|
||||||
|
buf = c_buffer("abcdef")
|
||||||
|
r = strchr(buf, "c")
|
||||||
|
x = r[0], r[1], r[2], r[3], r[4]
|
||||||
|
self.failUnlessEqual(x, ("c", "d", "e", "f", "\000"))
|
||||||
|
del buf
|
||||||
|
# x1 will NOT be the same as x, usually:
|
||||||
|
x1 = r[0], r[1], r[2], r[3], r[4]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
215
Lib/ctypes/test/test_strings.py
Normal file
215
Lib/ctypes/test/test_strings.py
Normal file
|
|
@ -0,0 +1,215 @@
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
class StringArrayTestCase(unittest.TestCase):
|
||||||
|
def test(self):
|
||||||
|
BUF = c_char * 4
|
||||||
|
|
||||||
|
buf = BUF("a", "b", "c")
|
||||||
|
self.failUnlessEqual(buf.value, "abc")
|
||||||
|
self.failUnlessEqual(buf.raw, "abc\000")
|
||||||
|
|
||||||
|
buf.value = "ABCD"
|
||||||
|
self.failUnlessEqual(buf.value, "ABCD")
|
||||||
|
self.failUnlessEqual(buf.raw, "ABCD")
|
||||||
|
|
||||||
|
buf.value = "x"
|
||||||
|
self.failUnlessEqual(buf.value, "x")
|
||||||
|
self.failUnlessEqual(buf.raw, "x\000CD")
|
||||||
|
|
||||||
|
buf[1] = "Z"
|
||||||
|
self.failUnlessEqual(buf.value, "xZCD")
|
||||||
|
self.failUnlessEqual(buf.raw, "xZCD")
|
||||||
|
|
||||||
|
self.assertRaises(ValueError, setattr, buf, "value", "aaaaaaaa")
|
||||||
|
self.assertRaises(TypeError, setattr, buf, "value", 42)
|
||||||
|
|
||||||
|
def test_c_buffer_value(self):
|
||||||
|
buf = c_buffer(32)
|
||||||
|
|
||||||
|
buf.value = "Hello, World"
|
||||||
|
self.failUnlessEqual(buf.value, "Hello, World")
|
||||||
|
|
||||||
|
self.failUnlessRaises(TypeError, setattr, buf, "value", buffer("Hello, World"))
|
||||||
|
self.assertRaises(TypeError, setattr, buf, "value", buffer("abc"))
|
||||||
|
self.assertRaises(ValueError, setattr, buf, "raw", buffer("x" * 100))
|
||||||
|
|
||||||
|
def test_c_buffer_raw(self):
|
||||||
|
buf = c_buffer(32)
|
||||||
|
|
||||||
|
buf.raw = buffer("Hello, World")
|
||||||
|
self.failUnlessEqual(buf.value, "Hello, World")
|
||||||
|
self.assertRaises(TypeError, setattr, buf, "value", buffer("abc"))
|
||||||
|
self.assertRaises(ValueError, setattr, buf, "raw", buffer("x" * 100))
|
||||||
|
|
||||||
|
def test_param_1(self):
|
||||||
|
BUF = c_char * 4
|
||||||
|
buf = BUF()
|
||||||
|
## print c_char_p.from_param(buf)
|
||||||
|
|
||||||
|
def test_param_2(self):
|
||||||
|
BUF = c_char * 4
|
||||||
|
buf = BUF()
|
||||||
|
## print BUF.from_param(c_char_p("python"))
|
||||||
|
## print BUF.from_param(BUF(*"pyth"))
|
||||||
|
|
||||||
|
try:
|
||||||
|
c_wchar
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
class WStringArrayTestCase(unittest.TestCase):
|
||||||
|
def test(self):
|
||||||
|
BUF = c_wchar * 4
|
||||||
|
|
||||||
|
buf = BUF(u"a", u"b", u"c")
|
||||||
|
self.failUnlessEqual(buf.value, u"abc")
|
||||||
|
|
||||||
|
buf.value = u"ABCD"
|
||||||
|
self.failUnlessEqual(buf.value, u"ABCD")
|
||||||
|
|
||||||
|
buf.value = u"x"
|
||||||
|
self.failUnlessEqual(buf.value, u"x")
|
||||||
|
|
||||||
|
buf[1] = u"Z"
|
||||||
|
self.failUnlessEqual(buf.value, u"xZCD")
|
||||||
|
|
||||||
|
class StringTestCase(unittest.TestCase):
|
||||||
|
def XX_test_basic_strings(self):
|
||||||
|
cs = c_string("abcdef")
|
||||||
|
|
||||||
|
# Cannot call len on a c_string any longer
|
||||||
|
self.assertRaises(TypeError, len, cs)
|
||||||
|
self.failUnlessEqual(sizeof(cs), 7)
|
||||||
|
|
||||||
|
# The value property is the string up to the first terminating NUL.
|
||||||
|
self.failUnlessEqual(cs.value, "abcdef")
|
||||||
|
self.failUnlessEqual(c_string("abc\000def").value, "abc")
|
||||||
|
|
||||||
|
# The raw property is the total buffer contents:
|
||||||
|
self.failUnlessEqual(cs.raw, "abcdef\000")
|
||||||
|
self.failUnlessEqual(c_string("abc\000def").raw, "abc\000def\000")
|
||||||
|
|
||||||
|
# We can change the value:
|
||||||
|
cs.value = "ab"
|
||||||
|
self.failUnlessEqual(cs.value, "ab")
|
||||||
|
self.failUnlessEqual(cs.raw, "ab\000\000\000\000\000")
|
||||||
|
|
||||||
|
cs.raw = "XY"
|
||||||
|
self.failUnlessEqual(cs.value, "XY")
|
||||||
|
self.failUnlessEqual(cs.raw, "XY\000\000\000\000\000")
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, c_string, u"123")
|
||||||
|
|
||||||
|
def XX_test_sized_strings(self):
|
||||||
|
|
||||||
|
# New in releases later than 0.4.0:
|
||||||
|
self.assertRaises(TypeError, c_string, None)
|
||||||
|
|
||||||
|
# New in releases later than 0.4.0:
|
||||||
|
# c_string(number) returns an empty string of size number
|
||||||
|
self.failUnless(len(c_string(32).raw) == 32)
|
||||||
|
self.assertRaises(ValueError, c_string, -1)
|
||||||
|
self.assertRaises(ValueError, c_string, 0)
|
||||||
|
|
||||||
|
# These tests fail, because it is no longer initialized
|
||||||
|
## self.failUnless(c_string(2).value == "")
|
||||||
|
## self.failUnless(c_string(2).raw == "\000\000")
|
||||||
|
self.failUnless(c_string(2).raw[-1] == "\000")
|
||||||
|
self.failUnless(len(c_string(2).raw) == 2)
|
||||||
|
|
||||||
|
def XX_test_initialized_strings(self):
|
||||||
|
|
||||||
|
self.failUnless(c_string("ab", 4).raw[:2] == "ab")
|
||||||
|
self.failUnless(c_string("ab", 4).raw[-1] == "\000")
|
||||||
|
self.failUnless(c_string("ab", 2).raw == "a\000")
|
||||||
|
|
||||||
|
def XX_test_toolong(self):
|
||||||
|
cs = c_string("abcdef")
|
||||||
|
# Much too long string:
|
||||||
|
self.assertRaises(ValueError, setattr, cs, "value", "123456789012345")
|
||||||
|
|
||||||
|
# One char too long values:
|
||||||
|
self.assertRaises(ValueError, setattr, cs, "value", "1234567")
|
||||||
|
|
||||||
|
## def test_perf(self):
|
||||||
|
## check_perf()
|
||||||
|
|
||||||
|
try:
|
||||||
|
c_wchar
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
class WStringTestCase(unittest.TestCase):
|
||||||
|
def test_wchar(self):
|
||||||
|
c_wchar(u"x")
|
||||||
|
repr(byref(c_wchar(u"x")))
|
||||||
|
c_wchar("x")
|
||||||
|
|
||||||
|
|
||||||
|
def X_test_basic_wstrings(self):
|
||||||
|
cs = c_wstring(u"abcdef")
|
||||||
|
|
||||||
|
# XXX This behaviour is about to change:
|
||||||
|
# len returns the size of the internal buffer in bytes.
|
||||||
|
# This includes the terminating NUL character.
|
||||||
|
self.failUnless(sizeof(cs) == 14)
|
||||||
|
|
||||||
|
# The value property is the string up to the first terminating NUL.
|
||||||
|
self.failUnless(cs.value == u"abcdef")
|
||||||
|
self.failUnless(c_wstring(u"abc\000def").value == u"abc")
|
||||||
|
|
||||||
|
self.failUnless(c_wstring(u"abc\000def").value == u"abc")
|
||||||
|
|
||||||
|
# The raw property is the total buffer contents:
|
||||||
|
self.failUnless(cs.raw == u"abcdef\000")
|
||||||
|
self.failUnless(c_wstring(u"abc\000def").raw == u"abc\000def\000")
|
||||||
|
|
||||||
|
# We can change the value:
|
||||||
|
cs.value = u"ab"
|
||||||
|
self.failUnless(cs.value == u"ab")
|
||||||
|
self.failUnless(cs.raw == u"ab\000\000\000\000\000")
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, c_wstring, "123")
|
||||||
|
self.assertRaises(ValueError, c_wstring, 0)
|
||||||
|
|
||||||
|
def X_test_toolong(self):
|
||||||
|
cs = c_wstring(u"abcdef")
|
||||||
|
# Much too long string:
|
||||||
|
self.assertRaises(ValueError, setattr, cs, "value", u"123456789012345")
|
||||||
|
|
||||||
|
# One char too long values:
|
||||||
|
self.assertRaises(ValueError, setattr, cs, "value", u"1234567")
|
||||||
|
|
||||||
|
|
||||||
|
def run_test(rep, msg, func, arg):
|
||||||
|
items = range(rep)
|
||||||
|
from time import clock
|
||||||
|
start = clock()
|
||||||
|
for i in items:
|
||||||
|
func(arg); func(arg); func(arg); func(arg); func(arg)
|
||||||
|
stop = clock()
|
||||||
|
print "%20s: %.2f us" % (msg, ((stop-start)*1e6/5/rep))
|
||||||
|
|
||||||
|
def check_perf():
|
||||||
|
# Construct 5 objects
|
||||||
|
|
||||||
|
REP = 200000
|
||||||
|
|
||||||
|
run_test(REP, "c_string(None)", c_string, None)
|
||||||
|
run_test(REP, "c_string('abc')", c_string, 'abc')
|
||||||
|
|
||||||
|
# Python 2.3 -OO, win2k, P4 700 MHz:
|
||||||
|
#
|
||||||
|
# c_string(None): 1.75 us
|
||||||
|
# c_string('abc'): 2.74 us
|
||||||
|
|
||||||
|
# Python 2.2 -OO, win2k, P4 700 MHz:
|
||||||
|
#
|
||||||
|
# c_string(None): 2.95 us
|
||||||
|
# c_string('abc'): 3.67 us
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
## check_perf()
|
||||||
|
unittest.main()
|
||||||
50
Lib/ctypes/test/test_struct_fields.py
Normal file
50
Lib/ctypes/test/test_struct_fields.py
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
class StructFieldsTestCase(unittest.TestCase):
|
||||||
|
# Structure/Union classes must get 'finalized' sooner or
|
||||||
|
# later, when one of these things happen:
|
||||||
|
#
|
||||||
|
# 1. _fields_ is set.
|
||||||
|
# 2. An instance is created.
|
||||||
|
# 3. The type is used as field of another Structure/Union.
|
||||||
|
# 4. The type is subclassed
|
||||||
|
#
|
||||||
|
# When they are finalized, assigning _fields_ is no longer allowed.
|
||||||
|
|
||||||
|
def test_1_A(self):
|
||||||
|
class X(Structure):
|
||||||
|
pass
|
||||||
|
self.failUnlessEqual(sizeof(X), 0) # not finalized
|
||||||
|
X._fields_ = [] # finalized
|
||||||
|
self.assertRaises(AttributeError, setattr, X, "_fields_", [])
|
||||||
|
|
||||||
|
def test_1_B(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [] # finalized
|
||||||
|
self.assertRaises(AttributeError, setattr, X, "_fields_", [])
|
||||||
|
|
||||||
|
def test_2(self):
|
||||||
|
class X(Structure):
|
||||||
|
pass
|
||||||
|
X()
|
||||||
|
self.assertRaises(AttributeError, setattr, X, "_fields_", [])
|
||||||
|
|
||||||
|
def test_3(self):
|
||||||
|
class X(Structure):
|
||||||
|
pass
|
||||||
|
class Y(Structure):
|
||||||
|
_fields_ = [("x", X)] # finalizes X
|
||||||
|
self.assertRaises(AttributeError, setattr, X, "_fields_", [])
|
||||||
|
|
||||||
|
def test_4(self):
|
||||||
|
class X(Structure):
|
||||||
|
pass
|
||||||
|
class Y(X):
|
||||||
|
pass
|
||||||
|
self.assertRaises(AttributeError, setattr, X, "_fields_", [])
|
||||||
|
Y._fields_ = []
|
||||||
|
self.assertRaises(AttributeError, setattr, X, "_fields_", [])
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
376
Lib/ctypes/test/test_structures.py
Normal file
376
Lib/ctypes/test/test_structures.py
Normal file
|
|
@ -0,0 +1,376 @@
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
from struct import calcsize
|
||||||
|
|
||||||
|
class SubclassesTest(unittest.TestCase):
|
||||||
|
def test_subclass(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_int)]
|
||||||
|
|
||||||
|
class Y(X):
|
||||||
|
_fields_ = [("b", c_int)]
|
||||||
|
|
||||||
|
class Z(X):
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_int))
|
||||||
|
self.failUnlessEqual(sizeof(Y), sizeof(c_int)*2)
|
||||||
|
self.failUnlessEqual(sizeof(Z), sizeof(c_int))
|
||||||
|
self.failUnlessEqual(X._fields_, [("a", c_int)])
|
||||||
|
self.failUnlessEqual(Y._fields_, [("b", c_int)])
|
||||||
|
self.failUnlessEqual(Z._fields_, [("a", c_int)])
|
||||||
|
|
||||||
|
def test_subclass_delayed(self):
|
||||||
|
class X(Structure):
|
||||||
|
pass
|
||||||
|
self.failUnlessEqual(sizeof(X), 0)
|
||||||
|
X._fields_ = [("a", c_int)]
|
||||||
|
|
||||||
|
class Y(X):
|
||||||
|
pass
|
||||||
|
self.failUnlessEqual(sizeof(Y), sizeof(X))
|
||||||
|
Y._fields_ = [("b", c_int)]
|
||||||
|
|
||||||
|
class Z(X):
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.failUnlessEqual(sizeof(X), sizeof(c_int))
|
||||||
|
self.failUnlessEqual(sizeof(Y), sizeof(c_int)*2)
|
||||||
|
self.failUnlessEqual(sizeof(Z), sizeof(c_int))
|
||||||
|
self.failUnlessEqual(X._fields_, [("a", c_int)])
|
||||||
|
self.failUnlessEqual(Y._fields_, [("b", c_int)])
|
||||||
|
self.failUnlessEqual(Z._fields_, [("a", c_int)])
|
||||||
|
|
||||||
|
class StructureTestCase(unittest.TestCase):
|
||||||
|
formats = {"c": c_char,
|
||||||
|
"b": c_byte,
|
||||||
|
"B": c_ubyte,
|
||||||
|
"h": c_short,
|
||||||
|
"H": c_ushort,
|
||||||
|
"i": c_int,
|
||||||
|
"I": c_uint,
|
||||||
|
"l": c_long,
|
||||||
|
"L": c_ulong,
|
||||||
|
"q": c_longlong,
|
||||||
|
"Q": c_ulonglong,
|
||||||
|
"f": c_float,
|
||||||
|
"d": c_double,
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_simple_structs(self):
|
||||||
|
for code, tp in self.formats.items():
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("x", c_char),
|
||||||
|
("y", tp)]
|
||||||
|
self.failUnlessEqual((sizeof(X), code),
|
||||||
|
(calcsize("c%c0%c" % (code, code)), code))
|
||||||
|
|
||||||
|
def test_unions(self):
|
||||||
|
for code, tp in self.formats.items():
|
||||||
|
class X(Union):
|
||||||
|
_fields_ = [("x", c_char),
|
||||||
|
("y", tp)]
|
||||||
|
self.failUnlessEqual((sizeof(X), code),
|
||||||
|
(calcsize("%c" % (code)), code))
|
||||||
|
|
||||||
|
def test_struct_alignment(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("x", c_char * 3)]
|
||||||
|
self.failUnlessEqual(alignment(X), calcsize("s"))
|
||||||
|
self.failUnlessEqual(sizeof(X), calcsize("3s"))
|
||||||
|
|
||||||
|
class Y(Structure):
|
||||||
|
_fields_ = [("x", c_char * 3),
|
||||||
|
("y", c_int)]
|
||||||
|
self.failUnlessEqual(alignment(Y), calcsize("i"))
|
||||||
|
self.failUnlessEqual(sizeof(Y), calcsize("3si"))
|
||||||
|
|
||||||
|
class SI(Structure):
|
||||||
|
_fields_ = [("a", X),
|
||||||
|
("b", Y)]
|
||||||
|
self.failUnlessEqual(alignment(SI), max(alignment(Y), alignment(X)))
|
||||||
|
self.failUnlessEqual(sizeof(SI), calcsize("3s0i 3si 0i"))
|
||||||
|
|
||||||
|
class IS(Structure):
|
||||||
|
_fields_ = [("b", Y),
|
||||||
|
("a", X)]
|
||||||
|
|
||||||
|
self.failUnlessEqual(alignment(SI), max(alignment(X), alignment(Y)))
|
||||||
|
self.failUnlessEqual(sizeof(IS), calcsize("3si 3s 0i"))
|
||||||
|
|
||||||
|
class XX(Structure):
|
||||||
|
_fields_ = [("a", X),
|
||||||
|
("b", X)]
|
||||||
|
self.failUnlessEqual(alignment(XX), alignment(X))
|
||||||
|
self.failUnlessEqual(sizeof(XX), calcsize("3s 3s 0s"))
|
||||||
|
|
||||||
|
def test_emtpy(self):
|
||||||
|
# I had problems with these
|
||||||
|
#
|
||||||
|
# Although these are patological cases: Empty Structures!
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = []
|
||||||
|
|
||||||
|
class Y(Union):
|
||||||
|
_fields_ = []
|
||||||
|
|
||||||
|
# Is this really the correct alignment, or should it be 0?
|
||||||
|
self.failUnless(alignment(X) == alignment(Y) == 1)
|
||||||
|
self.failUnless(sizeof(X) == sizeof(Y) == 0)
|
||||||
|
|
||||||
|
class XX(Structure):
|
||||||
|
_fields_ = [("a", X),
|
||||||
|
("b", X)]
|
||||||
|
|
||||||
|
self.failUnlessEqual(alignment(XX), 1)
|
||||||
|
self.failUnlessEqual(sizeof(XX), 0)
|
||||||
|
|
||||||
|
def test_fields(self):
|
||||||
|
# test the offset and size attributes of Structure/Unoin fields.
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("x", c_int),
|
||||||
|
("y", c_char)]
|
||||||
|
|
||||||
|
self.failUnlessEqual(X.x.offset, 0)
|
||||||
|
self.failUnlessEqual(X.x.size, sizeof(c_int))
|
||||||
|
|
||||||
|
self.failUnlessEqual(X.y.offset, sizeof(c_int))
|
||||||
|
self.failUnlessEqual(X.y.size, sizeof(c_char))
|
||||||
|
|
||||||
|
# readonly
|
||||||
|
self.assertRaises(TypeError, setattr, X.x, "offset", 92)
|
||||||
|
self.assertRaises(TypeError, setattr, X.x, "size", 92)
|
||||||
|
|
||||||
|
class X(Union):
|
||||||
|
_fields_ = [("x", c_int),
|
||||||
|
("y", c_char)]
|
||||||
|
|
||||||
|
self.failUnlessEqual(X.x.offset, 0)
|
||||||
|
self.failUnlessEqual(X.x.size, sizeof(c_int))
|
||||||
|
|
||||||
|
self.failUnlessEqual(X.y.offset, 0)
|
||||||
|
self.failUnlessEqual(X.y.size, sizeof(c_char))
|
||||||
|
|
||||||
|
# readonly
|
||||||
|
self.assertRaises(TypeError, setattr, X.x, "offset", 92)
|
||||||
|
self.assertRaises(TypeError, setattr, X.x, "size", 92)
|
||||||
|
|
||||||
|
# XXX Should we check nested data types also?
|
||||||
|
# offset is always relative to the class...
|
||||||
|
|
||||||
|
def test_packed(self):
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_byte),
|
||||||
|
("b", c_longlong)]
|
||||||
|
_pack_ = 1
|
||||||
|
|
||||||
|
self.failUnlessEqual(sizeof(X), 9)
|
||||||
|
self.failUnlessEqual(X.b.offset, 1)
|
||||||
|
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_byte),
|
||||||
|
("b", c_longlong)]
|
||||||
|
_pack_ = 2
|
||||||
|
self.failUnlessEqual(sizeof(X), 10)
|
||||||
|
self.failUnlessEqual(X.b.offset, 2)
|
||||||
|
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_byte),
|
||||||
|
("b", c_longlong)]
|
||||||
|
_pack_ = 4
|
||||||
|
self.failUnlessEqual(sizeof(X), 12)
|
||||||
|
self.failUnlessEqual(X.b.offset, 4)
|
||||||
|
|
||||||
|
import struct
|
||||||
|
longlong_size = struct.calcsize("q")
|
||||||
|
longlong_align = struct.calcsize("bq") - longlong_size
|
||||||
|
|
||||||
|
class X(Structure):
|
||||||
|
_fields_ = [("a", c_byte),
|
||||||
|
("b", c_longlong)]
|
||||||
|
_pack_ = 8
|
||||||
|
|
||||||
|
self.failUnlessEqual(sizeof(X), longlong_align + longlong_size)
|
||||||
|
self.failUnlessEqual(X.b.offset, min(8, longlong_align))
|
||||||
|
|
||||||
|
|
||||||
|
d = {"_fields_": [("a", "b"),
|
||||||
|
("b", "q")],
|
||||||
|
"_pack_": -1}
|
||||||
|
self.assertRaises(ValueError, type(Structure), "X", (Structure,), d)
|
||||||
|
|
||||||
|
def test_initializers(self):
|
||||||
|
class Person(Structure):
|
||||||
|
_fields_ = [("name", c_char*6),
|
||||||
|
("age", c_int)]
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, Person, 42)
|
||||||
|
self.assertRaises(ValueError, Person, "asldkjaslkdjaslkdj")
|
||||||
|
self.assertRaises(TypeError, Person, "Name", "HI")
|
||||||
|
|
||||||
|
# short enough
|
||||||
|
self.failUnlessEqual(Person("12345", 5).name, "12345")
|
||||||
|
# exact fit
|
||||||
|
self.failUnlessEqual(Person("123456", 5).name, "123456")
|
||||||
|
# too long
|
||||||
|
self.assertRaises(ValueError, Person, "1234567", 5)
|
||||||
|
|
||||||
|
|
||||||
|
def test_keyword_initializers(self):
|
||||||
|
class POINT(Structure):
|
||||||
|
_fields_ = [("x", c_int), ("y", c_int)]
|
||||||
|
pt = POINT(1, 2)
|
||||||
|
self.failUnlessEqual((pt.x, pt.y), (1, 2))
|
||||||
|
|
||||||
|
pt = POINT(y=2, x=1)
|
||||||
|
self.failUnlessEqual((pt.x, pt.y), (1, 2))
|
||||||
|
|
||||||
|
def test_invalid_field_types(self):
|
||||||
|
class POINT(Structure):
|
||||||
|
pass
|
||||||
|
self.assertRaises(TypeError, setattr, POINT, "_fields_", [("x", 1), ("y", 2)])
|
||||||
|
|
||||||
|
def test_intarray_fields(self):
|
||||||
|
class SomeInts(Structure):
|
||||||
|
_fields_ = [("a", c_int * 4)]
|
||||||
|
|
||||||
|
# can use tuple to initialize array (but not list!)
|
||||||
|
self.failUnlessEqual(SomeInts((1, 2)).a[:], [1, 2, 0, 0])
|
||||||
|
self.failUnlessEqual(SomeInts((1, 2, 3, 4)).a[:], [1, 2, 3, 4])
|
||||||
|
# too long
|
||||||
|
# XXX Should raise ValueError?, not RuntimeError
|
||||||
|
self.assertRaises(RuntimeError, SomeInts, (1, 2, 3, 4, 5))
|
||||||
|
|
||||||
|
def test_nested_initializers(self):
|
||||||
|
# test initializing nested structures
|
||||||
|
class Phone(Structure):
|
||||||
|
_fields_ = [("areacode", c_char*6),
|
||||||
|
("number", c_char*12)]
|
||||||
|
|
||||||
|
class Person(Structure):
|
||||||
|
_fields_ = [("name", c_char * 12),
|
||||||
|
("phone", Phone),
|
||||||
|
("age", c_int)]
|
||||||
|
|
||||||
|
p = Person("Someone", ("1234", "5678"), 5)
|
||||||
|
|
||||||
|
self.failUnlessEqual(p.name, "Someone")
|
||||||
|
self.failUnlessEqual(p.phone.areacode, "1234")
|
||||||
|
self.failUnlessEqual(p.phone.number, "5678")
|
||||||
|
self.failUnlessEqual(p.age, 5)
|
||||||
|
|
||||||
|
def test_structures_with_wchar(self):
|
||||||
|
try:
|
||||||
|
c_wchar
|
||||||
|
except NameError:
|
||||||
|
return # no unicode
|
||||||
|
|
||||||
|
class PersonW(Structure):
|
||||||
|
_fields_ = [("name", c_wchar * 12),
|
||||||
|
("age", c_int)]
|
||||||
|
|
||||||
|
p = PersonW(u"Someone")
|
||||||
|
self.failUnlessEqual(p.name, "Someone")
|
||||||
|
|
||||||
|
self.failUnlessEqual(PersonW(u"1234567890").name, u"1234567890")
|
||||||
|
self.failUnlessEqual(PersonW(u"12345678901").name, u"12345678901")
|
||||||
|
# exact fit
|
||||||
|
self.failUnlessEqual(PersonW(u"123456789012").name, u"123456789012")
|
||||||
|
#too long
|
||||||
|
self.assertRaises(ValueError, PersonW, u"1234567890123")
|
||||||
|
|
||||||
|
def test_init_errors(self):
|
||||||
|
class Phone(Structure):
|
||||||
|
_fields_ = [("areacode", c_char*6),
|
||||||
|
("number", c_char*12)]
|
||||||
|
|
||||||
|
class Person(Structure):
|
||||||
|
_fields_ = [("name", c_char * 12),
|
||||||
|
("phone", Phone),
|
||||||
|
("age", c_int)]
|
||||||
|
|
||||||
|
cls, msg = self.get_except(Person, "Someone", (1, 2))
|
||||||
|
self.failUnlessEqual(cls, RuntimeError)
|
||||||
|
# In Python 2.5, Exception is a new-style class, and the repr changed
|
||||||
|
if issubclass(Exception, object):
|
||||||
|
self.failUnlessEqual(msg,
|
||||||
|
"(Phone) <class 'exceptions.TypeError'>: "
|
||||||
|
"expected string or Unicode object, int found")
|
||||||
|
else:
|
||||||
|
self.failUnlessEqual(msg,
|
||||||
|
"(Phone) exceptions.TypeError: "
|
||||||
|
"expected string or Unicode object, int found")
|
||||||
|
|
||||||
|
cls, msg = self.get_except(Person, "Someone", ("a", "b", "c"))
|
||||||
|
self.failUnlessEqual(cls, RuntimeError)
|
||||||
|
if issubclass(Exception, object):
|
||||||
|
self.failUnlessEqual(msg,
|
||||||
|
"(Phone) <class 'exceptions.ValueError'>: too many initializers")
|
||||||
|
else:
|
||||||
|
self.failUnlessEqual(msg, "(Phone) exceptions.ValueError: too many initializers")
|
||||||
|
|
||||||
|
|
||||||
|
def get_except(self, func, *args):
|
||||||
|
try:
|
||||||
|
func(*args)
|
||||||
|
except Exception, detail:
|
||||||
|
return detail.__class__, str(detail)
|
||||||
|
|
||||||
|
|
||||||
|
## def test_subclass_creation(self):
|
||||||
|
## meta = type(Structure)
|
||||||
|
## # same as 'class X(Structure): pass'
|
||||||
|
## # fails, since we need either a _fields_ or a _abstract_ attribute
|
||||||
|
## cls, msg = self.get_except(meta, "X", (Structure,), {})
|
||||||
|
## self.failUnlessEqual((cls, msg),
|
||||||
|
## (AttributeError, "class must define a '_fields_' attribute"))
|
||||||
|
|
||||||
|
def test_abstract_class(self):
|
||||||
|
class X(Structure):
|
||||||
|
_abstract_ = "something"
|
||||||
|
# try 'X()'
|
||||||
|
cls, msg = self.get_except(eval, "X()", locals())
|
||||||
|
self.failUnlessEqual((cls, msg), (TypeError, "abstract class"))
|
||||||
|
|
||||||
|
def test_methods(self):
|
||||||
|
## class X(Structure):
|
||||||
|
## _fields_ = []
|
||||||
|
|
||||||
|
self.failUnless("in_dll" in dir(type(Structure)))
|
||||||
|
self.failUnless("from_address" in dir(type(Structure)))
|
||||||
|
self.failUnless("in_dll" in dir(type(Structure)))
|
||||||
|
|
||||||
|
class PointerMemberTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
# a Structure with a POINTER field
|
||||||
|
class S(Structure):
|
||||||
|
_fields_ = [("array", POINTER(c_int))]
|
||||||
|
|
||||||
|
s = S()
|
||||||
|
# We can assign arrays of the correct type
|
||||||
|
s.array = (c_int * 3)(1, 2, 3)
|
||||||
|
items = [s.array[i] for i in range(3)]
|
||||||
|
self.failUnlessEqual(items, [1, 2, 3])
|
||||||
|
|
||||||
|
# The following are bugs, but are included here because the unittests
|
||||||
|
# also describe the current behaviour.
|
||||||
|
#
|
||||||
|
# This fails with SystemError: bad arg to internal function
|
||||||
|
# or with IndexError (with a patch I have)
|
||||||
|
|
||||||
|
s.array[0] = 42
|
||||||
|
|
||||||
|
items = [s.array[i] for i in range(3)]
|
||||||
|
self.failUnlessEqual(items, [42, 2, 3])
|
||||||
|
|
||||||
|
s.array[0] = 1
|
||||||
|
|
||||||
|
## s.array[1] = 42
|
||||||
|
|
||||||
|
items = [s.array[i] for i in range(3)]
|
||||||
|
self.failUnlessEqual(items, [1, 2, 3])
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|
||||||
115
Lib/ctypes/test/test_unicode.py
Normal file
115
Lib/ctypes/test/test_unicode.py
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
# coding: latin-1
|
||||||
|
import unittest
|
||||||
|
import ctypes
|
||||||
|
|
||||||
|
try:
|
||||||
|
ctypes.c_wchar
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
import _ctypes_test
|
||||||
|
dll = ctypes.cdll.load(_ctypes_test.__file__)
|
||||||
|
wcslen = dll.my_wcslen
|
||||||
|
wcslen.argtypes = [ctypes.c_wchar_p]
|
||||||
|
|
||||||
|
|
||||||
|
class UnicodeTestCase(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.prev_conv_mode = ctypes.set_conversion_mode("ascii", "strict")
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
ctypes.set_conversion_mode(*self.prev_conv_mode)
|
||||||
|
|
||||||
|
def test_ascii_strict(self):
|
||||||
|
ctypes.set_conversion_mode("ascii", "strict")
|
||||||
|
# no conversions take place with unicode arguments
|
||||||
|
self.failUnlessEqual(wcslen(u"abc"), 3)
|
||||||
|
self.failUnlessEqual(wcslen(u"ab\u2070"), 3)
|
||||||
|
# string args are converted
|
||||||
|
self.failUnlessEqual(wcslen("abc"), 3)
|
||||||
|
self.failUnlessRaises(ctypes.ArgumentError, wcslen, "abä")
|
||||||
|
|
||||||
|
def test_ascii_replace(self):
|
||||||
|
ctypes.set_conversion_mode("ascii", "replace")
|
||||||
|
self.failUnlessEqual(wcslen(u"abc"), 3)
|
||||||
|
self.failUnlessEqual(wcslen(u"ab\u2070"), 3)
|
||||||
|
self.failUnlessEqual(wcslen("abc"), 3)
|
||||||
|
self.failUnlessEqual(wcslen("abä"), 3)
|
||||||
|
|
||||||
|
def test_ascii_ignore(self):
|
||||||
|
ctypes.set_conversion_mode("ascii", "ignore")
|
||||||
|
self.failUnlessEqual(wcslen(u"abc"), 3)
|
||||||
|
self.failUnlessEqual(wcslen(u"ab\u2070"), 3)
|
||||||
|
# ignore error mode skips non-ascii characters
|
||||||
|
self.failUnlessEqual(wcslen("abc"), 3)
|
||||||
|
self.failUnlessEqual(wcslen("äöüß"), 0)
|
||||||
|
|
||||||
|
def test_latin1_strict(self):
|
||||||
|
ctypes.set_conversion_mode("latin-1", "strict")
|
||||||
|
self.failUnlessEqual(wcslen(u"abc"), 3)
|
||||||
|
self.failUnlessEqual(wcslen(u"ab\u2070"), 3)
|
||||||
|
self.failUnlessEqual(wcslen("abc"), 3)
|
||||||
|
self.failUnlessEqual(wcslen("äöüß"), 4)
|
||||||
|
|
||||||
|
def test_buffers(self):
|
||||||
|
ctypes.set_conversion_mode("ascii", "strict")
|
||||||
|
buf = ctypes.create_unicode_buffer("abc")
|
||||||
|
self.failUnlessEqual(len(buf), 3+1)
|
||||||
|
|
||||||
|
ctypes.set_conversion_mode("ascii", "replace")
|
||||||
|
buf = ctypes.create_unicode_buffer("abäöü")
|
||||||
|
self.failUnlessEqual(buf[:], u"ab\uFFFD\uFFFD\uFFFD\0")
|
||||||
|
|
||||||
|
ctypes.set_conversion_mode("ascii", "ignore")
|
||||||
|
buf = ctypes.create_unicode_buffer("abäöü")
|
||||||
|
# is that correct? not sure. But with 'ignore', you get what you pay for..
|
||||||
|
self.failUnlessEqual(buf[:], u"ab\0\0\0\0")
|
||||||
|
|
||||||
|
import _ctypes_test
|
||||||
|
func = ctypes.cdll.load(_ctypes_test.__file__)._testfunc_p_p
|
||||||
|
|
||||||
|
class StringTestCase(UnicodeTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.prev_conv_mode = ctypes.set_conversion_mode("ascii", "strict")
|
||||||
|
func.argtypes = [ctypes.c_char_p]
|
||||||
|
func.restype = ctypes.c_char_p
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
ctypes.set_conversion_mode(*self.prev_conv_mode)
|
||||||
|
func.argtypes = None
|
||||||
|
func.restype = ctypes.c_int
|
||||||
|
|
||||||
|
def test_ascii_replace(self):
|
||||||
|
ctypes.set_conversion_mode("ascii", "strict")
|
||||||
|
self.failUnlessEqual(func("abc"), "abc")
|
||||||
|
self.failUnlessEqual(func(u"abc"), "abc")
|
||||||
|
self.assertRaises(ctypes.ArgumentError, func, u"abä")
|
||||||
|
|
||||||
|
def test_ascii_ignore(self):
|
||||||
|
ctypes.set_conversion_mode("ascii", "ignore")
|
||||||
|
self.failUnlessEqual(func("abc"), "abc")
|
||||||
|
self.failUnlessEqual(func(u"abc"), "abc")
|
||||||
|
self.failUnlessEqual(func(u"äöüß"), "")
|
||||||
|
|
||||||
|
def test_ascii_replace(self):
|
||||||
|
ctypes.set_conversion_mode("ascii", "replace")
|
||||||
|
self.failUnlessEqual(func("abc"), "abc")
|
||||||
|
self.failUnlessEqual(func(u"abc"), "abc")
|
||||||
|
self.failUnlessEqual(func(u"äöüß"), "????")
|
||||||
|
|
||||||
|
def test_buffers(self):
|
||||||
|
ctypes.set_conversion_mode("ascii", "strict")
|
||||||
|
buf = ctypes.create_string_buffer(u"abc")
|
||||||
|
self.failUnlessEqual(len(buf), 3+1)
|
||||||
|
|
||||||
|
ctypes.set_conversion_mode("ascii", "replace")
|
||||||
|
buf = ctypes.create_string_buffer(u"abäöü")
|
||||||
|
self.failUnlessEqual(buf[:], "ab???\0")
|
||||||
|
|
||||||
|
ctypes.set_conversion_mode("ascii", "ignore")
|
||||||
|
buf = ctypes.create_string_buffer(u"abäöü")
|
||||||
|
# is that correct? not sure. But with 'ignore', you get what you pay for..
|
||||||
|
self.failUnlessEqual(buf[:], "ab\0\0\0\0")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
82
Lib/ctypes/test/test_values.py
Normal file
82
Lib/ctypes/test/test_values.py
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
"""
|
||||||
|
A testcase which accesses *values* in a dll.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
import _ctypes_test
|
||||||
|
|
||||||
|
class ValuesTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_an_integer(self):
|
||||||
|
ctdll = cdll.load(_ctypes_test.__file__)
|
||||||
|
an_integer = c_int.in_dll(ctdll, "an_integer")
|
||||||
|
x = an_integer.value
|
||||||
|
self.failUnlessEqual(x, ctdll.get_an_integer())
|
||||||
|
an_integer.value *= 2
|
||||||
|
self.failUnlessEqual(x*2, ctdll.get_an_integer())
|
||||||
|
|
||||||
|
def test_undefined(self):
|
||||||
|
ctdll = cdll.load(_ctypes_test.__file__)
|
||||||
|
self.assertRaises(ValueError, c_int.in_dll, ctdll, "Undefined_Symbol")
|
||||||
|
|
||||||
|
class Win_ValuesTestCase(unittest.TestCase):
|
||||||
|
"""This test only works when python itself is a dll/shared library"""
|
||||||
|
|
||||||
|
def test_optimizeflag(self):
|
||||||
|
# This test accesses the Py_OptimizeFlag intger, which is
|
||||||
|
# exported by the Python dll.
|
||||||
|
|
||||||
|
# It's value is set depending on the -O and -OO flags:
|
||||||
|
# if not given, it is 0 and __debug__ is 1.
|
||||||
|
# If -O is given, the flag is 1, for -OO it is 2.
|
||||||
|
# docstrings are also removed in the latter case.
|
||||||
|
opt = c_int.in_dll(pydll, "Py_OptimizeFlag").value
|
||||||
|
if __debug__:
|
||||||
|
self.failUnlessEqual(opt, 0)
|
||||||
|
elif ValuesTestCase.__doc__ is not None:
|
||||||
|
self.failUnlessEqual(opt, 1)
|
||||||
|
else:
|
||||||
|
self.failUnlessEqual(opt, 2)
|
||||||
|
|
||||||
|
def test_frozentable(self):
|
||||||
|
# Python exports a PyImport_FrozenModules symbol. This is a
|
||||||
|
# pointer to an array of struct _frozen entries. The end of the
|
||||||
|
# array is marked by an entry containing a NULL name and zero
|
||||||
|
# size.
|
||||||
|
|
||||||
|
# In standard Python, this table contains a __hello__
|
||||||
|
# module, and a __phello__ package containing a spam
|
||||||
|
# module.
|
||||||
|
class struct_frozen(Structure):
|
||||||
|
_fields_ = [("name", c_char_p),
|
||||||
|
("code", POINTER(c_ubyte)),
|
||||||
|
("size", c_int)]
|
||||||
|
FrozenTable = POINTER(struct_frozen)
|
||||||
|
|
||||||
|
ft = FrozenTable.in_dll(pydll, "PyImport_FrozenModules")
|
||||||
|
# ft is a pointer to the struct_frozen entries:
|
||||||
|
items = []
|
||||||
|
for entry in ft:
|
||||||
|
# This is dangerous. We *can* iterate over a pointer, but
|
||||||
|
# the loop will not terminate (maybe with an access
|
||||||
|
# violation;-) because the pointer instance has no size.
|
||||||
|
if entry.name is None:
|
||||||
|
break
|
||||||
|
items.append((entry.name, entry.size))
|
||||||
|
import sys
|
||||||
|
if sys.version_info[:2] >= (2, 3):
|
||||||
|
expected = [("__hello__", 104), ("__phello__", -104), ("__phello__.spam", 104)]
|
||||||
|
else:
|
||||||
|
expected = [("__hello__", 100), ("__phello__", -100), ("__phello__.spam", 100)]
|
||||||
|
self.failUnlessEqual(items, expected)
|
||||||
|
|
||||||
|
from ctypes import _pointer_type_cache
|
||||||
|
del _pointer_type_cache[struct_frozen]
|
||||||
|
|
||||||
|
def test_undefined(self):
|
||||||
|
self.assertRaises(ValueError, c_int.in_dll, pydll, "Undefined_Symbol")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
64
Lib/ctypes/test/test_win32.py
Normal file
64
Lib/ctypes/test/test_win32.py
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
# Windows specific tests
|
||||||
|
|
||||||
|
from ctypes import *
|
||||||
|
import unittest, sys
|
||||||
|
|
||||||
|
import _ctypes_test
|
||||||
|
|
||||||
|
if sys.platform == "win32":
|
||||||
|
|
||||||
|
class WindowsTestCase(unittest.TestCase):
|
||||||
|
def test_callconv_1(self):
|
||||||
|
# Testing stdcall function
|
||||||
|
|
||||||
|
IsWindow = windll.user32.IsWindow
|
||||||
|
# ValueError: Procedure probably called with not enough arguments (4 bytes missing)
|
||||||
|
self.assertRaises(ValueError, IsWindow)
|
||||||
|
|
||||||
|
# This one should succeeed...
|
||||||
|
self.failUnlessEqual(0, IsWindow(0))
|
||||||
|
|
||||||
|
# ValueError: Procedure probably called with too many arguments (8 bytes in excess)
|
||||||
|
self.assertRaises(ValueError, IsWindow, 0, 0, 0)
|
||||||
|
|
||||||
|
def test_callconv_2(self):
|
||||||
|
# Calling stdcall function as cdecl
|
||||||
|
|
||||||
|
IsWindow = cdll.user32.IsWindow
|
||||||
|
|
||||||
|
# ValueError: Procedure called with not enough arguments (4 bytes missing)
|
||||||
|
# or wrong calling convention
|
||||||
|
self.assertRaises(ValueError, IsWindow, None)
|
||||||
|
|
||||||
|
def test_SEH(self):
|
||||||
|
# Call functions with invalid arguments, and make sure that access violations
|
||||||
|
# are trapped and raise an exception.
|
||||||
|
#
|
||||||
|
# Normally, in a debug build of the _ctypes extension
|
||||||
|
# module, exceptions are not trapped, so we can only run
|
||||||
|
# this test in a release build.
|
||||||
|
import sys
|
||||||
|
if not hasattr(sys, "getobjects"):
|
||||||
|
self.assertRaises(WindowsError, windll.kernel32.GetModuleHandleA, 32)
|
||||||
|
|
||||||
|
class Structures(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_struct_by_value(self):
|
||||||
|
class POINT(Structure):
|
||||||
|
_fields_ = [("x", c_long),
|
||||||
|
("y", c_long)]
|
||||||
|
|
||||||
|
class RECT(Structure):
|
||||||
|
_fields_ = [("left", c_long),
|
||||||
|
("top", c_long),
|
||||||
|
("right", c_long),
|
||||||
|
("bottom", c_long)]
|
||||||
|
|
||||||
|
dll = cdll.load(_ctypes_test.__file__)
|
||||||
|
|
||||||
|
pt = POINT(10, 10)
|
||||||
|
rect = RECT(0, 0, 20, 20)
|
||||||
|
self.failUnlessEqual(1, dll.PointInRect(byref(rect), pt))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
97
Lib/ctypes/wintypes.py
Normal file
97
Lib/ctypes/wintypes.py
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
# XXX This module needs cleanup.
|
||||||
|
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
DWORD = c_ulong
|
||||||
|
WORD = c_ushort
|
||||||
|
BYTE = c_byte
|
||||||
|
|
||||||
|
ULONG = c_ulong
|
||||||
|
LONG = c_long
|
||||||
|
|
||||||
|
LARGE_INTEGER = c_longlong
|
||||||
|
ULARGE_INTEGER = c_ulonglong
|
||||||
|
|
||||||
|
|
||||||
|
HANDLE = c_ulong # in the header files: void *
|
||||||
|
|
||||||
|
HWND = HANDLE
|
||||||
|
HDC = HANDLE
|
||||||
|
HMODULE = HANDLE
|
||||||
|
HINSTANCE = HANDLE
|
||||||
|
HRGN = HANDLE
|
||||||
|
HTASK = HANDLE
|
||||||
|
HKEY = HANDLE
|
||||||
|
HPEN = HANDLE
|
||||||
|
HGDIOBJ = HANDLE
|
||||||
|
HMENU = HANDLE
|
||||||
|
|
||||||
|
LCID = DWORD
|
||||||
|
|
||||||
|
WPARAM = c_uint
|
||||||
|
LPARAM = c_long
|
||||||
|
|
||||||
|
BOOL = c_long
|
||||||
|
VARIANT_BOOL = c_short
|
||||||
|
|
||||||
|
LPCOLESTR = LPOLESTR = OLESTR = c_wchar_p
|
||||||
|
LPCWSTR = LPWSTR = c_wchar_p
|
||||||
|
|
||||||
|
LPCSTR = LPSTR = c_char_p
|
||||||
|
|
||||||
|
class RECT(Structure):
|
||||||
|
_fields_ = [("left", c_long),
|
||||||
|
("top", c_long),
|
||||||
|
("right", c_long),
|
||||||
|
("bottom", c_long)]
|
||||||
|
RECTL = RECT
|
||||||
|
|
||||||
|
class POINT(Structure):
|
||||||
|
_fields_ = [("x", c_long),
|
||||||
|
("y", c_long)]
|
||||||
|
POINTL = POINT
|
||||||
|
|
||||||
|
class SIZE(Structure):
|
||||||
|
_fields_ = [("cx", c_long),
|
||||||
|
("cy", c_long)]
|
||||||
|
SIZEL = SIZE
|
||||||
|
|
||||||
|
def RGB(red, green, blue):
|
||||||
|
return red + (green << 8) + (blue << 16)
|
||||||
|
|
||||||
|
class FILETIME(Structure):
|
||||||
|
_fields_ = [("dwLowDateTime", DWORD),
|
||||||
|
("dwHighDateTime", DWORD)]
|
||||||
|
|
||||||
|
class MSG(Structure):
|
||||||
|
_fields_ = [("hWnd", HWND),
|
||||||
|
("message", c_uint),
|
||||||
|
("wParam", WPARAM),
|
||||||
|
("lParam", LPARAM),
|
||||||
|
("time", DWORD),
|
||||||
|
("pt", POINT)]
|
||||||
|
MAX_PATH = 260
|
||||||
|
|
||||||
|
class WIN32_FIND_DATAA(Structure):
|
||||||
|
_fields_ = [("dwFileAttributes", DWORD),
|
||||||
|
("ftCreationTime", FILETIME),
|
||||||
|
("ftLastAccessTime", FILETIME),
|
||||||
|
("ftLastWriteTime", FILETIME),
|
||||||
|
("nFileSizeHigh", DWORD),
|
||||||
|
("nFileSizeLow", DWORD),
|
||||||
|
("dwReserved0", DWORD),
|
||||||
|
("dwReserved1", DWORD),
|
||||||
|
("cFileName", c_char * MAX_PATH),
|
||||||
|
("cAlternameFileName", c_char * 14)]
|
||||||
|
|
||||||
|
class WIN32_FIND_DATAW(Structure):
|
||||||
|
_fields_ = [("dwFileAttributes", DWORD),
|
||||||
|
("ftCreationTime", FILETIME),
|
||||||
|
("ftLastAccessTime", FILETIME),
|
||||||
|
("ftLastWriteTime", FILETIME),
|
||||||
|
("nFileSizeHigh", DWORD),
|
||||||
|
("nFileSizeLow", DWORD),
|
||||||
|
("dwReserved0", DWORD),
|
||||||
|
("dwReserved1", DWORD),
|
||||||
|
("cFileName", c_wchar * MAX_PATH),
|
||||||
|
("cAlternameFileName", c_wchar * 14)]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue