Commit babddfca authored by Thomas Heller's avatar Thomas Heller

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

parent cf567c1b
# -*- 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
This diff is collapsed.
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")
# 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()
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/
\ No newline at end of file
"""
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'
"""
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()
"""
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()
#!/bin/sh
svn export --force http://svn.red-bean.com/bob/macholib/trunk/macholib/ .
svn export --force http://svn.red-bean.com/bob/macholib/trunk/macholib/ .
"""
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()
*.pyc
*.pyo
_testfile.py
_testfile.xml
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
"""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))
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()
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()
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()
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()
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()
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()
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()
# 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()
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()
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")
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()
This diff is collapsed.
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()
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()
# superseeded by test_numbers.py
import unittest
if __name__ == '__main__':
unittest.main()
# 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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
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()
# 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()
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()
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()
This diff is collapsed.
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()
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment