mirror of https://github.com/python/cpython
Merge in changes from ctypes 0.9.9.6 upstream version.
This commit is contained in:
parent
4b75a7c1cf
commit
6ff67ef096
|
@ -3,7 +3,7 @@
|
|||
import os as _os, sys as _sys
|
||||
from itertools import chain as _chain
|
||||
|
||||
__version__ = "0.9.9.4"
|
||||
__version__ = "0.9.9.6"
|
||||
|
||||
from _ctypes import Union, Structure, Array
|
||||
from _ctypes import _Pointer
|
||||
|
@ -23,8 +23,6 @@ if _os.name in ("nt", "ce"):
|
|||
from _ctypes import FUNCFLAG_CDECL as _FUNCFLAG_CDECL, \
|
||||
FUNCFLAG_PYTHONAPI as _FUNCFLAG_PYTHONAPI
|
||||
|
||||
from ctypes._loader import LibraryLoader
|
||||
|
||||
"""
|
||||
WINOLEAPI -> HRESULT
|
||||
WINOLEAPI_(type)
|
||||
|
@ -72,9 +70,11 @@ def CFUNCTYPE(restype, *argtypes):
|
|||
The function prototype can be called in three ways to create a
|
||||
callable object:
|
||||
|
||||
prototype(funct) - returns a C callable function calling funct
|
||||
prototype(vtbl_index, method_name[, paramflags]) - a Python callable that calls a COM method
|
||||
prototype(funct_name, dll[, paramflags]) - a Python callable that calls an exported function in a dll
|
||||
prototype(integer address) -> foreign function
|
||||
prototype(callable) -> create and return a C callable function from callable
|
||||
prototype(integer index, method name[, paramflags]) -> foreign function calling a COM method
|
||||
prototype((ordinal number, dll object)[, paramflags]) -> foreign function exported by ordinal
|
||||
prototype((function name, dll object)[, paramflags]) -> foreign function exported by name
|
||||
"""
|
||||
try:
|
||||
return _c_functype_cache[(restype, argtypes)]
|
||||
|
@ -352,6 +352,23 @@ if _os.name in ("nt", "ce"):
|
|||
_flags_ = _FUNCFLAG_STDCALL
|
||||
_restype_ = HRESULT
|
||||
|
||||
class LibraryLoader(object):
|
||||
def __init__(self, dlltype):
|
||||
self._dlltype = dlltype
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name[0] == '_':
|
||||
raise AttributeError(name)
|
||||
dll = self._dlltype(name)
|
||||
setattr(self, name, dll)
|
||||
return dll
|
||||
|
||||
def __getitem__(self, name):
|
||||
return getattr(self, name)
|
||||
|
||||
def LoadLibrary(self, name):
|
||||
return self._dlltype(name)
|
||||
|
||||
cdll = LibraryLoader(CDLL)
|
||||
pydll = LibraryLoader(PyDLL)
|
||||
|
||||
|
@ -402,7 +419,12 @@ def PYFUNCTYPE(restype, *argtypes):
|
|||
_restype_ = restype
|
||||
_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
|
||||
return CFunctionType
|
||||
cast = PYFUNCTYPE(py_object, c_void_p, py_object)(_cast_addr)
|
||||
_cast = PYFUNCTYPE(py_object, c_void_p, py_object)(_cast_addr)
|
||||
|
||||
def cast(obj, typ):
|
||||
result = _cast(obj, typ)
|
||||
result.__keepref = obj
|
||||
return result
|
||||
|
||||
_string_at = CFUNCTYPE(py_object, c_void_p, c_int)(_string_at_addr)
|
||||
def string_at(ptr, size=0):
|
||||
|
|
|
@ -1,262 +0,0 @@
|
|||
import sys, os
|
||||
import ctypes
|
||||
|
||||
if os.name in ("nt", "ce"):
|
||||
from _ctypes import LoadLibrary as dlopen
|
||||
else:
|
||||
from _ctypes import dlopen
|
||||
from _ctypes import 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:
|
||||
cmd = 'ldd %s 2>/dev/null' % sys.executable
|
||||
res = re.search(expr, os.popen(cmd).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()
|
|
@ -24,7 +24,7 @@ class BITS(Structure):
|
|||
("R", c_short, 6),
|
||||
("S", c_short, 7)]
|
||||
|
||||
func = cdll.load(_ctypes_test.__file__).unpack_bitfields
|
||||
func = CDLL(_ctypes_test.__file__).unpack_bitfields
|
||||
func.argtypes = POINTER(BITS), c_char
|
||||
|
||||
##for n in "ABCDEFGHIMNOPQRS":
|
||||
|
|
|
@ -15,7 +15,7 @@ def bin(s):
|
|||
|
||||
class Test(unittest.TestCase):
|
||||
def X_test(self):
|
||||
print sys.byteorder
|
||||
print >> sys.stderr, sys.byteorder
|
||||
for i in range(32):
|
||||
bits = BITS()
|
||||
setattr(bits, "i%s" % i, 1)
|
||||
|
|
|
@ -115,7 +115,7 @@ 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__)
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
|
||||
# The function prototype called by 'integrate': double func(double);
|
||||
CALLBACK = CFUNCTYPE(c_double, c_double)
|
||||
|
|
|
@ -23,33 +23,24 @@ class Test(unittest.TestCase):
|
|||
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])
|
||||
|
||||
ptr = cast(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])
|
||||
from sys import getrefcount
|
||||
|
||||
# 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]
|
||||
before = getrefcount(array)
|
||||
ptr = cast(array, POINTER(c_int))
|
||||
self.failUnlessEqual(getrefcount(array), before + 1)
|
||||
del ptr
|
||||
self.failUnlessEqual(getrefcount(array), before)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -7,7 +7,7 @@ from ctypes import *
|
|||
import _ctypes_test
|
||||
|
||||
class CFunctions(unittest.TestCase):
|
||||
_dll = cdll.load(_ctypes_test.__file__)
|
||||
_dll = CDLL(_ctypes_test.__file__)
|
||||
|
||||
def S(self):
|
||||
return c_longlong.in_dll(self._dll, "last_tf_arg_s").value
|
||||
|
|
|
@ -14,7 +14,7 @@ class Test(unittest.TestCase):
|
|||
def test_checkretval(self):
|
||||
|
||||
import _ctypes_test
|
||||
dll = cdll.load(_ctypes_test.__file__)
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
self.failUnlessEqual(42, dll._testfunc_p_p(42))
|
||||
|
||||
dll._testfunc_p_p.restype = CHECKED
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
import unittest
|
||||
import os, sys
|
||||
from ctypes import *
|
||||
from ctypes.util import find_library
|
||||
from ctypes.test import is_resource_enabled
|
||||
|
||||
if sys.platform == "win32":
|
||||
lib_gl = find_library("OpenGL32")
|
||||
lib_glu = find_library("Glu32")
|
||||
lib_glut = find_library("glut32")
|
||||
lib_gle = None
|
||||
elif sys.platform == "darwin":
|
||||
lib_gl = lib_glu = find_library("OpenGL")
|
||||
lib_glut = find_library("GLUT")
|
||||
lib_gle = None
|
||||
else:
|
||||
lib_gl = find_library("GL")
|
||||
lib_glu = find_library("GLU")
|
||||
lib_glut = find_library("glut")
|
||||
lib_gle = find_library("gle")
|
||||
|
||||
## print, for debugging
|
||||
if is_resource_enabled("printing"):
|
||||
if lib_gl or lib_glu or lib_glut or lib_gle:
|
||||
print "OpenGL libraries:"
|
||||
for item in (("GL", lib_gl),
|
||||
("GLU", lib_glu),
|
||||
("glut", lib_glut),
|
||||
("gle", lib_gle)):
|
||||
print "\t", item
|
||||
|
||||
|
||||
# On some systems, loading the OpenGL libraries needs the RTLD_GLOBAL mode.
|
||||
class Test_OpenGL_libs(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.gl = self.glu = self.gle = self.glut = None
|
||||
if lib_gl:
|
||||
self.gl = CDLL(lib_gl, mode=RTLD_GLOBAL)
|
||||
if lib_glu:
|
||||
self.glu = CDLL(lib_glu, RTLD_GLOBAL)
|
||||
if lib_glut:
|
||||
self.glut = CDLL(lib_glut)
|
||||
if lib_gle:
|
||||
self.gle = CDLL(lib_gle)
|
||||
|
||||
if lib_gl:
|
||||
def test_gl(self):
|
||||
if self.gl:
|
||||
self.gl.glClearIndex
|
||||
|
||||
if lib_glu:
|
||||
def test_glu(self):
|
||||
if self.glu:
|
||||
self.glu.gluBeginCurve
|
||||
|
||||
if lib_glut:
|
||||
def test_glut(self):
|
||||
if self.glut:
|
||||
self.glut.glutWireTetrahedron
|
||||
|
||||
if lib_gle:
|
||||
def test_gle(self):
|
||||
if self.gle:
|
||||
self.gle.gleGetJoinStyle
|
||||
|
||||
##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()
|
|
@ -8,7 +8,7 @@ except NameError:
|
|||
WINFUNCTYPE = CFUNCTYPE
|
||||
|
||||
import _ctypes_test
|
||||
lib = cdll.load(_ctypes_test.__file__)
|
||||
lib = CDLL(_ctypes_test.__file__)
|
||||
|
||||
class CFuncPtrTestCase(unittest.TestCase):
|
||||
def test_basic(self):
|
||||
|
|
|
@ -15,9 +15,9 @@ except NameError:
|
|||
WINFUNCTYPE = CFUNCTYPE
|
||||
|
||||
import _ctypes_test
|
||||
dll = cdll.load(_ctypes_test.__file__)
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
if sys.platform == "win32":
|
||||
windll = windll.load(_ctypes_test.__file__)
|
||||
windll = WinDLL(_ctypes_test.__file__)
|
||||
|
||||
class POINT(Structure):
|
||||
_fields_ = [("x", c_int), ("y", c_int)]
|
||||
|
|
|
@ -4,7 +4,7 @@ import unittest
|
|||
from ctypes import *
|
||||
import _ctypes_test
|
||||
|
||||
lib = cdll.load(_ctypes_test.__file__)
|
||||
lib = CDLL(_ctypes_test.__file__)
|
||||
|
||||
class LibTest(unittest.TestCase):
|
||||
def test_sqrt(self):
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
from ctypes import *
|
||||
import sys, unittest
|
||||
import os, StringIO
|
||||
from ctypes.util import find_library
|
||||
from ctypes.test import is_resource_enabled
|
||||
|
||||
libc_name = None
|
||||
if os.name == "nt":
|
||||
|
@ -18,39 +20,49 @@ else:
|
|||
libc_name = line.split()[4]
|
||||
else:
|
||||
libc_name = line.split()[2]
|
||||
## print "libc_name is", libc_name
|
||||
break
|
||||
|
||||
if is_resource_enabled("printing"):
|
||||
print "libc_name is", libc_name
|
||||
|
||||
class LoaderTest(unittest.TestCase):
|
||||
|
||||
unknowndll = "xxrandomnamexx"
|
||||
|
||||
if libc_name is not None:
|
||||
def test_load(self):
|
||||
cdll.load(libc_name)
|
||||
cdll.load(os.path.basename(libc_name))
|
||||
self.assertRaises(OSError, cdll.load, self.unknowndll)
|
||||
CDLL(libc_name)
|
||||
CDLL(os.path.basename(libc_name))
|
||||
self.assertRaises(OSError, CDLL, self.unknowndll)
|
||||
|
||||
if libc_name is not None and os.path.basename(libc_name) == "libc.so.6":
|
||||
def test_load_version(self):
|
||||
cdll.load_version("c", "6")
|
||||
cdll.LoadLibrary("libc.so.6")
|
||||
# linux uses version, libc 9 should not exist
|
||||
self.assertRaises(OSError, cdll.load_version, "c", "9")
|
||||
self.assertRaises(OSError, cdll.load_version, self.unknowndll, "")
|
||||
self.assertRaises(OSError, cdll.LoadLibrary, "libc.so.9")
|
||||
self.assertRaises(OSError, cdll.LoadLibrary, self.unknowndll)
|
||||
|
||||
def test_find(self):
|
||||
name = "c"
|
||||
cdll.find(name)
|
||||
self.assertRaises(OSError, cdll.find, self.unknowndll)
|
||||
def test_find(self):
|
||||
for name in ("c", "m"):
|
||||
lib = find_library(name)
|
||||
if lib:
|
||||
cdll.LoadLibrary(lib)
|
||||
CDLL(lib)
|
||||
|
||||
if os.name in ("nt", "ce"):
|
||||
def test_load_library(self):
|
||||
if is_resource_enabled("printing"):
|
||||
print find_library("kernel32")
|
||||
print find_library("user32")
|
||||
|
||||
if os.name == "nt":
|
||||
windll.load_library("kernel32").GetModuleHandleW
|
||||
windll.kernel32.GetModuleHandleW
|
||||
windll["kernel32"].GetModuleHandleW
|
||||
windll.LoadLibrary("kernel32").GetModuleHandleW
|
||||
WinDLL("kernel32").GetModuleHandleW
|
||||
elif os.name == "ce":
|
||||
windll.load_library("coredll").GetModuleHandleW
|
||||
windll.coredll.GetModuleHandleW
|
||||
windll["coredll"].GetModuleHandleW
|
||||
windll.LoadLibrary("coredll").GetModuleHandleW
|
||||
WinDLL("coredll").GetModuleHandleW
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class PointersTestCase(unittest.TestCase):
|
|||
self.failUnlessRaises(TypeError, A, c_ulong(33))
|
||||
|
||||
def test_pass_pointers(self):
|
||||
dll = cdll.load(_ctypes_test.__file__)
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
func = dll._testfunc_p_p
|
||||
func.restype = c_long
|
||||
|
||||
|
@ -35,7 +35,7 @@ class PointersTestCase(unittest.TestCase):
|
|||
self.failUnlessEqual(res[0], 12345678)
|
||||
|
||||
def test_change_pointers(self):
|
||||
dll = cdll.load(_ctypes_test.__file__)
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
func = dll._testfunc_p_p
|
||||
|
||||
i = c_int(87654)
|
||||
|
@ -70,7 +70,7 @@ class PointersTestCase(unittest.TestCase):
|
|||
return 0
|
||||
callback = PROTOTYPE(func)
|
||||
|
||||
dll = cdll.load(_ctypes_test.__file__)
|
||||
dll = CDLL(_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
|
||||
|
@ -156,7 +156,7 @@ class PointersTestCase(unittest.TestCase):
|
|||
|
||||
def test_charpp( self ):
|
||||
"""Test that a character pointer-to-pointer is correctly passed"""
|
||||
dll = cdll.load(_ctypes_test.__file__)
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
func = dll._testfunc_c_p_p
|
||||
func.restype = c_char_p
|
||||
argv = (c_char_p * 2)()
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
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):
|
||||
if os.path.exists('/usr/lib/libGL.so'):
|
||||
cdll.load('libGL.so', mode=RTLD_GLOBAL)
|
||||
if os.path.exists('/usr/lib/libGLU.so'):
|
||||
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()
|
|
@ -22,7 +22,7 @@ import unittest
|
|||
# In this case, there would have to be an additional reference to the argument...
|
||||
|
||||
import _ctypes_test
|
||||
testdll = cdll.load(_ctypes_test.__file__)
|
||||
testdll = CDLL(_ctypes_test.__file__)
|
||||
|
||||
# Return machine address `a` as a (possibly long) non-negative integer.
|
||||
# Starting with Python 2.5, id(anything) is always non-negative, and
|
||||
|
|
|
@ -6,7 +6,7 @@ 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__)
|
||||
dll = ctypes.CDLL(_ctypes_test.__file__)
|
||||
|
||||
class RefcountTestCase(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ 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__)
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
get_strchr = dll.get_strchr
|
||||
get_strchr.restype = CFUNCTYPE(c_char_p, c_char_p, c_char)
|
||||
strchr = get_strchr()
|
||||
|
@ -18,7 +18,7 @@ class ReturnFuncPtrTestCase(unittest.TestCase):
|
|||
self.assertRaises(TypeError, strchr, "abcdef")
|
||||
|
||||
def test_without_prototype(self):
|
||||
dll = cdll.load(_ctypes_test.__file__)
|
||||
dll = CDLL(_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
|
||||
|
|
|
@ -37,7 +37,7 @@ class SlicesTestCase(unittest.TestCase):
|
|||
def test_char_ptr(self):
|
||||
s = "abcdefghijklmnopqrstuvwxyz\0"
|
||||
|
||||
dll = cdll.load(_ctypes_test.__file__)
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
dll.my_strdup.restype = POINTER(c_char)
|
||||
res = dll.my_strdup(s)
|
||||
self.failUnlessEqual(res[:len(s)], s)
|
||||
|
@ -65,7 +65,7 @@ class SlicesTestCase(unittest.TestCase):
|
|||
def test_wchar_ptr(self):
|
||||
s = u"abcdefghijklmnopqrstuvwxyz\0"
|
||||
|
||||
dll = cdll.load(_ctypes_test.__file__)
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
dll.my_wcsdup.restype = POINTER(c_wchar)
|
||||
dll.my_wcsdup.argtypes = POINTER(c_wchar),
|
||||
res = dll.my_wcsdup(s)
|
||||
|
|
|
@ -3,7 +3,7 @@ from ctypes import *
|
|||
|
||||
import _ctypes_test
|
||||
|
||||
lib = cdll.load(_ctypes_test.__file__)
|
||||
lib = CDLL(_ctypes_test.__file__)
|
||||
|
||||
class StringPtrTestCase(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ except AttributeError:
|
|||
pass
|
||||
else:
|
||||
import _ctypes_test
|
||||
dll = ctypes.cdll.load(_ctypes_test.__file__)
|
||||
dll = ctypes.CDLL(_ctypes_test.__file__)
|
||||
wcslen = dll.my_wcslen
|
||||
wcslen.argtypes = [ctypes.c_wchar_p]
|
||||
|
||||
|
@ -66,7 +66,7 @@ else:
|
|||
self.failUnlessEqual(buf[:], u"ab\0\0\0\0")
|
||||
|
||||
import _ctypes_test
|
||||
func = ctypes.cdll.load(_ctypes_test.__file__)._testfunc_p_p
|
||||
func = ctypes.CDLL(_ctypes_test.__file__)._testfunc_p_p
|
||||
|
||||
class StringTestCase(UnicodeTestCase):
|
||||
def setUp(self):
|
||||
|
|
|
@ -10,7 +10,7 @@ import _ctypes_test
|
|||
class ValuesTestCase(unittest.TestCase):
|
||||
|
||||
def test_an_integer(self):
|
||||
ctdll = cdll.load(_ctypes_test.__file__)
|
||||
ctdll = CDLL(_ctypes_test.__file__)
|
||||
an_integer = c_int.in_dll(ctdll, "an_integer")
|
||||
x = an_integer.value
|
||||
self.failUnlessEqual(x, ctdll.get_an_integer())
|
||||
|
@ -18,7 +18,7 @@ class ValuesTestCase(unittest.TestCase):
|
|||
self.failUnlessEqual(x*2, ctdll.get_an_integer())
|
||||
|
||||
def test_undefined(self):
|
||||
ctdll = cdll.load(_ctypes_test.__file__)
|
||||
ctdll = CDLL(_ctypes_test.__file__)
|
||||
self.assertRaises(ValueError, c_int.in_dll, ctdll, "Undefined_Symbol")
|
||||
|
||||
class Win_ValuesTestCase(unittest.TestCase):
|
||||
|
|
|
@ -54,7 +54,7 @@ class Structures(unittest.TestCase):
|
|||
("right", c_long),
|
||||
("bottom", c_long)]
|
||||
|
||||
dll = cdll.load(_ctypes_test.__file__)
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
|
||||
pt = POINT(10, 10)
|
||||
rect = RECT(0, 0, 20, 20)
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
import sys, os
|
||||
import ctypes
|
||||
|
||||
# find_library(name) returns the pathname of a library, or None.
|
||||
if os.name == "nt":
|
||||
def find_library(name):
|
||||
# See MSDN for the REAL search order.
|
||||
for directory in os.environ['PATH'].split(os.pathsep):
|
||||
fname = os.path.join(directory, name)
|
||||
if os.path.exists(fname):
|
||||
return fname
|
||||
if fname.lower().endswith(".dll"):
|
||||
continue
|
||||
fname = fname + ".dll"
|
||||
if os.path.exists(fname):
|
||||
return fname
|
||||
return None
|
||||
|
||||
if os.name == "ce":
|
||||
# search path according to MSDN:
|
||||
# - absolute path specified by filename
|
||||
# - The .exe launch directory
|
||||
# - the Windows directory
|
||||
# - ROM dll files (where are they?)
|
||||
# - OEM specified search path: HKLM\Loader\SystemPath
|
||||
def find_library(name):
|
||||
return name
|
||||
|
||||
if os.name == "posix" and sys.platform == "darwin":
|
||||
from ctypes.macholib.dyld import dyld_find as _dyld_find
|
||||
def find_library(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 None
|
||||
|
||||
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:
|
||||
# Hm, this works only for libs needed by the python executable.
|
||||
cmd = 'ldd %s 2>/dev/null' % sys.executable
|
||||
res = re.search(expr, os.popen(cmd).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 None
|
||||
return res.group(1)
|
||||
|
||||
def find_library(name):
|
||||
lib = _findLib_ld(name) or _findLib_gcc(name)
|
||||
if not lib:
|
||||
return None
|
||||
return _get_soname(lib)
|
||||
|
||||
################################################################
|
||||
# test code
|
||||
|
||||
def test():
|
||||
from ctypes import cdll
|
||||
if os.name == "nt":
|
||||
print cdll.msvcrt
|
||||
print cdll.load("msvcrt")
|
||||
print find_library("msvcrt")
|
||||
|
||||
if os.name == "posix":
|
||||
# find and load_version
|
||||
print find_library("m")
|
||||
print find_library("c")
|
||||
print find_library("bz2")
|
||||
|
||||
# getattr
|
||||
## print cdll.m
|
||||
## print cdll.bz2
|
||||
|
||||
# load
|
||||
if sys.platform == "darwin":
|
||||
print cdll.LoadLibrary("libm.dylib")
|
||||
print cdll.LoadLibrary("libcrypto.dylib")
|
||||
print cdll.LoadLibrary("libSystem.dylib")
|
||||
print cdll.LoadLibrary("System.framework/System")
|
||||
else:
|
||||
print cdll.LoadLibrary("libm.so")
|
||||
print cdll.LoadLibrary("libcrypt.so")
|
||||
print find_library("crypt")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
Loading…
Reference in New Issue