[1.1.X] 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.

Backport of r11979 from trunk.


git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.1.X@11980 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2009-12-24 15:01:47 +00:00
parent 116ff7ff35
commit 94b718915d
2 changed files with 22 additions and 15 deletions

View File

@ -104,7 +104,7 @@ geos_version.restype = c_char_p
# Regular expression should be able to parse version strings such as # 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' # '3.0.0rc4-CAPI-1.3.3', or '3.0.0-CAPI-1.4.1'
version_regex = re.compile(r'^(?P<version>(?P<major>\d+)\.(?P<minor>\d+)\.\d+)(rc(?P<release_candidate>\d+))?-CAPI-(?P<capi_version>\d+\.\d+\.\d+)$') version_regex = re.compile(r'^(?P<version>(?P<major>\d+)\.(?P<minor>\d+)\.(?P<subminor>\d+))(rc(?P<release_candidate>\d+))?-CAPI-(?P<capi_version>\d+\.\d+\.\d+)$')
def geos_version_info(): def geos_version_info():
""" """
Returns a dictionary containing the various version metadata parsed from Returns a dictionary containing the various version metadata parsed from
@ -115,14 +115,16 @@ def geos_version_info():
ver = geos_version() ver = geos_version()
m = version_regex.match(ver) m = version_regex.match(ver)
if not m: raise GEOSException('Could not parse version info string "%s"' % 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. # Version numbers and whether or not prepared geometry support is available.
_verinfo = geos_version_info() _verinfo = geos_version_info()
GEOS_MAJOR_VERSION = int(_verinfo['major']) GEOS_MAJOR_VERSION = int(_verinfo['major'])
GEOS_MINOR_VERSION = int(_verinfo['minor']) GEOS_MINOR_VERSION = int(_verinfo['minor'])
GEOS_SUBMINOR_VERSION = int(_verinfo['subminor'])
del _verinfo 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. # Calling the finishGEOS() upon exit of the interpreter.
atexit.register(lgeos.finishGEOS) atexit.register(lgeos.finishGEOS)

View File

@ -1,22 +1,27 @@
""" """
Error checking functions for GEOS ctypes prototype functions. Error checking functions for GEOS ctypes prototype functions.
""" """
import os from ctypes import c_void_p, string_at, CDLL
from ctypes import string_at, CDLL
from ctypes.util import find_library
from django.contrib.gis.geos.error import GEOSException 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 # Getting the `free` routine used to free the memory allocated for
# returned from GEOS. # string pointers returned by GEOS.
if os.name == 'nt': if GEOS_VERSION >= (3, 1, 0):
libc_name = 'msvcrt' # 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: else:
libc_name = 'libc' # Getting the `free` routine from the C library of the platform.
libc = CDLL(find_library(libc_name)) # The C library is obtained by passing None into `CDLL`.
libc = CDLL(None)
free = libc.free
### ctypes error checking routines ### ### ctypes error checking routines ###
def last_arg_byref(args): 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 return args[-1]._obj.value
def check_dbl(result, func, cargs): def check_dbl(result, func, cargs):
@ -60,7 +65,7 @@ def check_sized_string(result, func, cargs):
# correct size. # correct size.
s = string_at(result, last_arg_byref(cargs)) s = string_at(result, last_arg_byref(cargs))
# Freeing the memory allocated within GEOS # Freeing the memory allocated within GEOS
libc.free(result) free(result)
return s return s
def check_string(result, func, cargs): def check_string(result, func, cargs):
@ -73,7 +78,7 @@ def check_string(result, func, cargs):
# Getting the string value at the pointer address. # Getting the string value at the pointer address.
s = string_at(result) s = string_at(result)
# Freeing the memory allocated within GEOS # Freeing the memory allocated within GEOS
libc.free(result) free(result)
return s return s
def check_zero(result, func, cargs): def check_zero(result, func, cargs):