Copy ctypes-0.9.9.4 Python modules from external into the trunk.

This commit is contained in:
Thomas Heller 2006-03-08 19:56:54 +00:00
parent cf567c1b9c
commit babddfca75
59 changed files with 5941 additions and 0 deletions

14
Lib/ctypes/.CTYPES_DEVEL Normal file
View 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
View File

@ -0,0 +1,4 @@
*.pyc
*.pyo
com

489
Lib/ctypes/__init__.py Normal file
View 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
View 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
View 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()

View File

@ -0,0 +1,3 @@
*.pyc
*.pyo
.svn

View 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/

View 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
View 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()

View 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()

View File

@ -0,0 +1,2 @@
#!/bin/sh
svn export --force http://svn.red-bean.com/bob/macholib/trunk/macholib/ .

View File

@ -0,0 +1 @@
svn export --force http://svn.red-bean.com/bob/macholib/trunk/macholib/ .

View 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()

View File

@ -0,0 +1,4 @@
*.pyc
*.pyo
_testfile.py
_testfile.xml

202
Lib/ctypes/test/__init__.py Normal file
View 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

View 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))

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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")

View 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()

View 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()

View 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()

View 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()

View File

@ -0,0 +1,5 @@
# superseeded by test_numbers.py
import unittest
if __name__ == '__main__':
unittest.main()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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()

View 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
View 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)]