From 474fb8c3ae9edd2c26ce5dd3e6c57db7c61976ed Mon Sep 17 00:00:00 2001 From: Justin Bronn Date: Thu, 24 Dec 2009 14:53:51 +0000 Subject: [PATCH] Fixed #12438 -- now use `GEOSFree` to free string pointers allocated within GEOS when available; now parse out subminor version, and added a `GEOS_VERSION` tuple. git-svn-id: http://code.djangoproject.com/svn/django/trunk@11979 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/gis/geos/libgeos.py | 8 +++-- .../contrib/gis/geos/prototypes/errcheck.py | 29 +++++++++++-------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/django/contrib/gis/geos/libgeos.py b/django/contrib/gis/geos/libgeos.py index f1aecb0de5..244bfa7967 100644 --- a/django/contrib/gis/geos/libgeos.py +++ b/django/contrib/gis/geos/libgeos.py @@ -104,7 +104,7 @@ geos_version.restype = c_char_p # Regular expression should be able to parse version strings such as # '3.0.0rc4-CAPI-1.3.3', or '3.0.0-CAPI-1.4.1' -version_regex = re.compile(r'^(?P(?P\d+)\.(?P\d+)\.\d+)(rc(?P\d+))?-CAPI-(?P\d+\.\d+\.\d+)$') +version_regex = re.compile(r'^(?P(?P\d+)\.(?P\d+)\.(?P\d+))(rc(?P\d+))?-CAPI-(?P\d+\.\d+\.\d+)$') def geos_version_info(): """ Returns a dictionary containing the various version metadata parsed from @@ -115,14 +115,16 @@ def geos_version_info(): ver = geos_version() m = version_regex.match(ver) if not m: raise GEOSException('Could not parse version info string "%s"' % ver) - return dict((key, m.group(key)) for key in ('version', 'release_candidate', 'capi_version', 'major', 'minor')) + return dict((key, m.group(key)) for key in ('version', 'release_candidate', 'capi_version', 'major', 'minor', 'subminor')) # Version numbers and whether or not prepared geometry support is available. _verinfo = geos_version_info() GEOS_MAJOR_VERSION = int(_verinfo['major']) GEOS_MINOR_VERSION = int(_verinfo['minor']) +GEOS_SUBMINOR_VERSION = int(_verinfo['subminor']) del _verinfo -GEOS_PREPARE = GEOS_MAJOR_VERSION > 3 or GEOS_MAJOR_VERSION == 3 and GEOS_MINOR_VERSION >= 1 +GEOS_VERSION = (GEOS_MAJOR_VERSION, GEOS_MINOR_VERSION, GEOS_SUBMINOR_VERSION) +GEOS_PREPARE = GEOS_VERSION >= (3, 1, 0) # Calling the finishGEOS() upon exit of the interpreter. atexit.register(lgeos.finishGEOS) diff --git a/django/contrib/gis/geos/prototypes/errcheck.py b/django/contrib/gis/geos/prototypes/errcheck.py index d96a1ac753..c5037c1e21 100644 --- a/django/contrib/gis/geos/prototypes/errcheck.py +++ b/django/contrib/gis/geos/prototypes/errcheck.py @@ -1,22 +1,27 @@ """ Error checking functions for GEOS ctypes prototype functions. """ -import os -from ctypes import string_at, CDLL -from ctypes.util import find_library +from ctypes import c_void_p, string_at, CDLL from django.contrib.gis.geos.error import GEOSException +from django.contrib.gis.geos.libgeos import lgeos, GEOS_VERSION -# Getting the C library, needed to free the string pointers -# returned from GEOS. -if os.name == 'nt': - libc_name = 'msvcrt' +# Getting the `free` routine used to free the memory allocated for +# string pointers returned by GEOS. +if GEOS_VERSION >= (3, 1, 0): + # In versions 3.1 and above, `GEOSFree` was added to the C API + # because `free` isn't always available on all platforms. + free = lgeos.GEOSFree + free.argtypes = [c_void_p] + free.restype = None else: - libc_name = 'libc' -libc = CDLL(find_library(libc_name)) + # Getting the `free` routine from the C library of the platform. + # The C library is obtained by passing None into `CDLL`. + libc = CDLL(None) + free = libc.free ### ctypes error checking routines ### def last_arg_byref(args): - "Returns the last C argument's by reference value." + "Returns the last C argument's value by reference." return args[-1]._obj.value def check_dbl(result, func, cargs): @@ -60,7 +65,7 @@ def check_sized_string(result, func, cargs): # correct size. s = string_at(result, last_arg_byref(cargs)) # Freeing the memory allocated within GEOS - libc.free(result) + free(result) return s def check_string(result, func, cargs): @@ -73,7 +78,7 @@ def check_string(result, func, cargs): # Getting the string value at the pointer address. s = string_at(result) # Freeing the memory allocated within GEOS - libc.free(result) + free(result) return s def check_zero(result, func, cargs):