[GRASS-SVN] r42331 - grass/trunk/lib/python/ctypes
svn_grass at osgeo.org
svn_grass at osgeo.org
Fri May 21 11:26:07 EDT 2010
Author: glynn
Date: 2010-05-21 11:26:06 -0400 (Fri, 21 May 2010)
New Revision: 42331
Added:
grass/trunk/lib/python/ctypes/loader.py
grass/trunk/lib/python/ctypes/preamble.py
Modified:
grass/trunk/lib/python/ctypes/Makefile
Log:
Eliminate String wrapper; just use c_char_p
Modified: grass/trunk/lib/python/ctypes/Makefile
===================================================================
--- grass/trunk/lib/python/ctypes/Makefile 2010-05-21 10:31:25 UTC (rev 42330)
+++ grass/trunk/lib/python/ctypes/Makefile 2010-05-21 15:26:06 UTC (rev 42331)
@@ -51,7 +51,7 @@
SED = sed
CTYPESFLAGS = $(INC)
-EXTRA_CLEAN_FILES := $(foreach M,$(MODULES),$(M).py) ctypesheader.py
+EXTRA_CLEAN_FILES := $(foreach M,$(MODULES),$(M).py)
ifneq ($(MINGW),)
EXTRA_LIBS = $(INTLLIB)
@@ -63,8 +63,8 @@
GDIR = $(PYDIR)/grass
DSTDIR = $(GDIR)/lib
-PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__ ctypesheader)
-PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__ ctypesheader)
+PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__ ctypes_preamble ctypes_loader)
+PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__ ctypes_preamble ctypes_loader)
LPYFILES := $(patsubst %,%.py,$(MODULES))
ifneq ($(strip $(CTYPESGEN)),)
@@ -76,25 +76,19 @@
$(DSTDIR)/%.py: %.py | $(DSTDIR)
$(SED) \
-e '/^# End loader$$/a\
- from ctypesheader import *\
- from ctypesheader import _variadic_function' \
+ from ctypes_preamble import *\
+ from ctypes_preamble import _variadic_function\
+ from ctypes_loader import *' \
-e '/^# Begin preamble$$/,/^# End preamble$$/d' \
-e '/^# Begin loader$$/,/^# End loader$$/d' \
$< > $@
-# $(INSTALL_DATA) $< $@
+$(DSTDIR)/ctypes_%.py: %.py | $(DSTDIR)
+ $(INSTALL_DATA) $< $@
+
%.py: $(%_INC) $(%_LIBS)
$(call run_grass,$(CTYPESGEN) $(CTYPESFLAGS) $($*_LIBS) $(EXTRA_LIBS) $(patsubst %.h,$(ARCH_INCDIR)/%.h,$($*_INC)) -o $@)
-$(DSTDIR)/ctypesheader.py: ctypesheader.py | $(DSTDIR)
- $(INSTALL_DATA) $< $@
-
-ctypesheader.py: grass.py
- $(SED) -n \
- -e '/^# Begin preamble$$/,/^# End preamble$$/p' \
- -e '/^# Begin loader$$/,/^# End loader$$/p' \
- $< > $@
-
$(PYDIR):
$(MKDIR) $@
Added: grass/trunk/lib/python/ctypes/loader.py
===================================================================
--- grass/trunk/lib/python/ctypes/loader.py (rev 0)
+++ grass/trunk/lib/python/ctypes/loader.py 2010-05-21 15:26:06 UTC (rev 42331)
@@ -0,0 +1,248 @@
+# ----------------------------------------------------------------------------
+# Copyright (c) 2008 David James
+# Copyright (c) 2006-2008 Alex Holkner
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of pyglet nor the names of its
+# contributors may be used to endorse or promote products
+# derived from this software without specific prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ----------------------------------------------------------------------------
+
+import os.path, re, sys, glob
+import ctypes
+import ctypes.util
+
+def _environ_path(name):
+ if name in os.environ:
+ return os.environ[name].split(":")
+ else:
+ return []
+
+class LibraryLoader(object):
+ def __init__(self):
+ self.other_dirs=[]
+
+ def load_library(self,libname):
+ """Given the name of a library, load it."""
+ paths = self.getpaths(libname)
+
+ for path in paths:
+ if os.path.exists(path):
+ return self.load(path)
+
+ raise ImportError,"%s not found." % libname
+
+ def load(self,path):
+ """Given a path to a library, load it."""
+ try:
+ # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead
+ # of the default RTLD_LOCAL. Without this, you end up with
+ # libraries not being loadable, resulting in "Symbol not found"
+ # errors
+ if sys.platform == 'darwin':
+ return ctypes.CDLL(path, ctypes.RTLD_GLOBAL)
+ else:
+ return ctypes.cdll.LoadLibrary(path)
+ except OSError,e:
+ raise ImportError,e
+
+ def getpaths(self,libname):
+ """Return a list of paths where the library might be found."""
+ if os.path.isabs(libname):
+ yield libname
+
+ else:
+ for path in self.getplatformpaths(libname):
+ yield path
+
+ path = ctypes.util.find_library(libname)
+ if path: yield path
+
+ def getplatformpaths(self, libname):
+ return []
+
+# Darwin (Mac OS X)
+
+class DarwinLibraryLoader(LibraryLoader):
+ name_formats = ["lib%s.dylib", "lib%s.so", "lib%s.bundle", "%s.dylib",
+ "%s.so", "%s.bundle", "%s"]
+
+ def getplatformpaths(self,libname):
+ if os.path.pathsep in libname:
+ names = [libname]
+ else:
+ names = [format % libname for format in self.name_formats]
+
+ for dir in self.getdirs(libname):
+ for name in names:
+ yield os.path.join(dir,name)
+
+ def getdirs(self,libname):
+ '''Implements the dylib search as specified in Apple documentation:
+
+ http://developer.apple.com/documentation/DeveloperTools/Conceptual/
+ DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html
+
+ Before commencing the standard search, the method first checks
+ the bundle's ``Frameworks`` directory if the application is running
+ within a bundle (OS X .app).
+ '''
+
+ dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH")
+ if not dyld_fallback_library_path:
+ dyld_fallback_library_path = [os.path.expanduser('~/lib'),
+ '/usr/local/lib', '/usr/lib']
+
+ dirs = []
+
+ if '/' in libname:
+ dirs.extend(_environ_path("DYLD_LIBRARY_PATH"))
+ else:
+ dirs.extend(_environ_path("LD_LIBRARY_PATH"))
+ dirs.extend(_environ_path("DYLD_LIBRARY_PATH"))
+
+ dirs.extend(self.other_dirs)
+ dirs.append(".")
+
+ if hasattr(sys, 'frozen') and sys.frozen == 'macosx_app':
+ dirs.append(os.path.join(
+ os.environ['RESOURCEPATH'],
+ '..',
+ 'Frameworks'))
+
+ dirs.extend(dyld_fallback_library_path)
+
+ return dirs
+
+# Posix
+
+class PosixLibraryLoader(LibraryLoader):
+ _ld_so_cache = None
+
+ def _create_ld_so_cache(self):
+ # Recreate search path followed by ld.so. This is going to be
+ # slow to build, and incorrect (ld.so uses ld.so.cache, which may
+ # not be up-to-date). Used only as fallback for distros without
+ # /sbin/ldconfig.
+ #
+ # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted.
+
+ directories = []
+ for name in ("LD_LIBRARY_PATH",
+ "SHLIB_PATH", # HPUX
+ "LIBPATH", # OS/2, AIX
+ "LIBRARY_PATH", # BE/OS
+ ):
+ if name in os.environ:
+ directories.extend(os.environ[name].split(os.pathsep))
+ directories.extend(self.other_dirs)
+ directories.append(".")
+
+ try: directories.extend([dir.strip() for dir in open('/etc/ld.so.conf')])
+ except IOError: pass
+
+ directories.extend(['/lib', '/usr/lib', '/lib64', '/usr/lib64'])
+
+ cache = {}
+ lib_re = re.compile(r'lib(.*)\.s[ol]')
+ ext_re = re.compile(r'\.s[ol]$')
+ for dir in directories:
+ try:
+ for path in glob.glob("%s/*.s[ol]*" % dir):
+ file = os.path.basename(path)
+
+ # Index by filename
+ if file not in cache:
+ cache[file] = path
+
+ # Index by library name
+ match = lib_re.match(file)
+ if match:
+ library = match.group(1)
+ if library not in cache:
+ cache[library] = path
+ except OSError:
+ pass
+
+ self._ld_so_cache = cache
+
+ def getplatformpaths(self, libname):
+ if self._ld_so_cache is None:
+ self._create_ld_so_cache()
+
+ result = self._ld_so_cache.get(libname)
+ if result: yield result
+
+ path = ctypes.util.find_library(libname)
+ if path: yield os.path.join("/lib",path)
+
+# Windows
+
+class _WindowsLibrary(object):
+ def __init__(self, path):
+ self.cdll = ctypes.cdll.LoadLibrary(path)
+ self.windll = ctypes.windll.LoadLibrary(path)
+
+ def __getattr__(self, name):
+ try: return getattr(self.cdll,name)
+ except AttributeError:
+ try: return getattr(self.windll,name)
+ except AttributeError:
+ raise
+
+class WindowsLibraryLoader(LibraryLoader):
+ name_formats = ["%s.dll", "lib%s.dll"]
+
+ def load(self, path):
+ return _WindowsLibrary(path)
+
+ def getplatformpaths(self, libname):
+ if os.path.sep not in libname:
+ for name in self.name_formats:
+ path = ctypes.util.find_library(name % libname)
+ if path:
+ yield path
+
+# Platform switching
+
+# If your value of sys.platform does not appear in this dict, please contact
+# the Ctypesgen maintainers.
+
+loaderclass = {
+ "darwin": DarwinLibraryLoader,
+ "cygwin": WindowsLibraryLoader,
+ "win32": WindowsLibraryLoader
+}
+
+loader = loaderclass.get(sys.platform, PosixLibraryLoader)()
+
+def add_library_search_dirs(other_dirs):
+ loader.other_dirs = other_dirs
+
+load_library = loader.load_library
+
+del loaderclass
Added: grass/trunk/lib/python/ctypes/preamble.py
===================================================================
--- grass/trunk/lib/python/ctypes/preamble.py (rev 0)
+++ grass/trunk/lib/python/ctypes/preamble.py 2010-05-21 15:26:06 UTC (rev 42331)
@@ -0,0 +1,72 @@
+import ctypes, os, sys
+from ctypes import *
+
+_int_types = (c_int16, c_int32)
+if hasattr(ctypes, 'c_int64'):
+ # Some builds of ctypes apparently do not have c_int64
+ # defined; it's a pretty good bet that these builds do not
+ # have 64-bit pointers.
+ _int_types += (c_int64,)
+for t in _int_types:
+ if sizeof(t) == sizeof(c_size_t):
+ c_ptrdiff_t = t
+del t
+del _int_types
+
+class c_void(Structure):
+ # c_void_p is a buggy return type, converting to int, so
+ # POINTER(None) == c_void_p is actually written as
+ # POINTER(c_void), so it can be treated as a real pointer.
+ _fields_ = [('dummy', c_int)]
+
+def POINTER(obj):
+ p = ctypes.POINTER(obj)
+
+ # Convert None to a real NULL pointer to work around bugs
+ # in how ctypes handles None on 64-bit platforms
+ if not isinstance(p.from_param, classmethod):
+ def from_param(cls, x):
+ if x is None:
+ return cls()
+ else:
+ return x
+ p.from_param = classmethod(from_param)
+
+ return p
+
+String = c_char_p
+ReturnString = c_char_p
+
+# As of ctypes 1.0, ctypes does not support custom error-checking
+# functions on callbacks, nor does it support custom datatypes on
+# callbacks, so we must ensure that all callbacks return
+# primitive datatypes.
+#
+# Non-primitive return values wrapped with UNCHECKED won't be
+# typechecked, and will be converted to c_void_p.
+def UNCHECKED(type):
+ if (hasattr(type, "_type_") and isinstance(type._type_, str)
+ and type._type_ != "P"):
+ return type
+ else:
+ return c_void_p
+
+# ctypes doesn't have direct support for variadic functions, so we have to write
+# our own wrapper class
+class _variadic_function(object):
+ def __init__(self,func,restype,argtypes):
+ self.func=func
+ self.func.restype=restype
+ self.argtypes=argtypes
+ def _as_parameter_(self):
+ # So we can pass this variadic function as a function pointer
+ return self.func
+ def __call__(self,*args):
+ fixed_args=[]
+ i=0
+ for argtype in self.argtypes:
+ # Typecheck what we can
+ fixed_args.append(argtype.from_param(args[i]))
+ i+=1
+ return self.func(*fixed_args+list(args[i:]))
+
More information about the grass-commit
mailing list