[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