Index: geos.py
===================================================================
--- geos.py	(revision 1203)
+++ geos.py	(working copy)
@@ -54,10 +54,40 @@
 class allocated_c_char_p(c_char_p):
     pass
 
+# Get the version information about the GEOS c-api.
+version_tuple = c_char_p(_lgeos.GEOSversion()).value.split('-')[2]
+geos_c_version = tuple(int(n) for n in version_tuple.split('.'))
+
+# If we have the new interface, then record a baseline so that we know what
+# additional functions are declared in ctypes_declarations.
+if geos_c_version >= (1,5,0):
+    start_set = set(_lgeos.__dict__)
+
 # Load the ctypes restype and argtype declarations for geos_c functions.
 _here = os.path.abspath(os.path.dirname(__file__))
 execfile(os.path.join(_here, 'ctypes_declarations.py'))
 
+# If we have the new interface, automatically detect all function declarations,
+# and declare their re-entrant counterpart.
+if geos_c_version >= (1,5,0):
+    end_set = set(_lgeos.__dict__)
+    new_func_names = end_set - start_set
+
+    for func_name in new_func_names:
+        new_func_name = "%s_r" % func_name
+        if hasattr(_lgeos, new_func_name):
+            new_func = getattr(_lgeos, new_func_name)
+            old_func = getattr(_lgeos, func_name)
+            if old_func.argtypes is None:
+                # Handle functions that didn't take an argument before, finishGEOS.
+                new_func.argtypes = [c_void_p]
+            else:
+                new_func.argtypes = [c_void_p] + old_func.argtypes
+
+    # Handle special case.
+    _lgeos.initGEOS_r.restype = c_void_p
+    _lgeos.initGEOS_r.argtypes = [c_void_p, c_void_p]            
+
 # Exceptions
 
 class ReadingError(Exception):
@@ -72,15 +102,16 @@
 class PredicateError(Exception):
     pass
 
-thread_data = local()
-thread_data.geos_handle = None
-
 def error_handler(fmt, list):
+    print "ERROR: '%s'" % (list)
     pass
+
 error_h = CFUNCTYPE(None, c_char_p, c_char_p)(error_handler)
 
 def notice_handler(fmt, list):
+    print "NOTICE: '%s'" % (list)
     pass
+
 notice_h = CFUNCTYPE(None, c_char_p, c_char_p)(notice_handler)
 
 def cleanup():
@@ -89,40 +120,63 @@
         
 atexit.register(cleanup)
 
-class LGEOS(object):
+import time
+import functools
+
+class LGEOS(local):
     
     def __init__(self, dll):
         self._lgeos = dll
-        v = self._lgeos.GEOSversion().split('-')[2]
-        self._geos_c_version = tuple(int(n) for n in v.split('.'))
-        if self._geos_c_version >= (1,5,0):
-            self._lgeos.initGEOS_r.restype = c_void_p
-            self._lgeos.initGEOS_r.argtypes = [c_void_p, c_void_p]            
-            thread_data.geos_handle = self._lgeos.initGEOS_r(notice_h, error_h)
-            
+
     def __getattr__(self, name):
-        func = getattr(self._lgeos, name)
-        if self._geos_c_version >= (1,5,0):
-            ob = getattr(self._lgeos, name + '_r')
-            class wrapper(object):
-                __name__ = None
-                errcheck = None
-                restype = None
-                def __init__(self):
-                    self.func = ob
-                    self.__name__ = ob.__name__
-                    self.func.restype = func.restype
-                    if func.argtypes is None: self.func.argtypes = None
-                    else: self.func.argtypes = [c_void_p] + func.argtypes                    
-                def __call__(self, *args):
-                    if self.errcheck is not None:
-                        self.func.errcheck = self.errcheck
-                    if self.restype is not None:
-                        self.func.restype = self.restype
-                    return self.func(thread_data.geos_handle, *args)
-            attr = wrapper()
+        if 'geos_handle' == name:
+            self.geos_handle = lgeos._lgeos.initGEOS_r(notice_h, error_h)
+            return self.geos_handle
+
+        old_func = getattr(self._lgeos, name)
+        if geos_c_version >= (1,5,0):
+            real_func = getattr(self._lgeos, name + '_r')
+
+            #attr = wrapper(old_func, real_func)
+            attr = functools.partial(real_func, self.geos_handle)
+            attr.__name__ = real_func.__name__
         else:
-            attr = func
+            attr = old_func
+
+        # Store the function, or function wrapper in a thread specific attribute.
+        setattr(self, name, attr)
         return attr
         
-lgeos = LGEOS(_lgeos)
\ No newline at end of file
+lgeos = LGEOS(_lgeos)
+
+func = lgeos.GEOSGeomToWKB_buf
+def errcheck_wkb(result, func, argtuple):
+   size_ref = argtuple[2]
+   size = size_ref._obj
+   retval = ctypes.string_at(result, size.value)[:]
+   free(result)
+   return retval
+func.func.errcheck = errcheck_wkb
+
+def errcheck_just_free(result, func, argtuple):
+   retval = result.value
+   free(result)
+   return retval
+
+func = lgeos.GEOSGeomToWKT
+func.func.errcheck = errcheck_just_free
+func = lgeos.GEOSRelate
+func.func.errcheck = errcheck_just_free
+
+def errcheck_predicate(result, func, argtuple):
+    if result == 2:
+        raise PredicateError, "Failed to evaluate %s" % repr(func)
+    return result
+
+for pred in [lgeos.GEOSDisjoint, lgeos.GEOSTouches, lgeos.GEOSIntersects, lgeos.GEOSCrosses,
+             lgeos.GEOSWithin, lgeos.GEOSContains, lgeos.GEOSOverlaps, lgeos.GEOSEquals]:
+    pred.func.errcheck = errcheck_predicate
+
+for pred in [lgeos.GEOSisEmpty, lgeos.GEOSisValid, lgeos.GEOSisSimple,
+             lgeos.GEOSisRing, lgeos.GEOSHasZ]:
+    pred.func.errcheck = errcheck_predicate
Index: predicates.py
===================================================================
--- predicates.py	(revision 1203)
+++ predicates.py	(working copy)
@@ -16,11 +16,11 @@
 
     def __init__(self, fn):
         self.fn = fn
-        def errcheck(result, func, argtuple):
-            if result == 2:
-                raise PredicateError, "Failed to evaluate %s" % repr(self.fn)
-            return result
-        self.fn.errcheck = errcheck
+        #def errcheck(result, func, argtuple):
+        #    if result == 2:
+        #        raise PredicateError, "Failed to evaluate %s" % repr(self.fn)
+        #    return result
+        #self.fn.errcheck = errcheck
 
     def __get__(self, obj, objtype=None):
         if not obj._geom:
@@ -44,11 +44,11 @@
 
     def __init__(self, fn):
         self.fn = fn
-        def errcheck(result, func, argtuple):
-            if result == 2:
-                raise PredicateError, "Failed to evaluate %s" % repr(self.fn)
-            return result
-        self.fn.errcheck = errcheck
+#        def errcheck(result, func, argtuple):
+#            if result == 2:
+#                raise PredicateError, "Failed to evaluate %s" % repr(self.fn)
+#            return result
+#        self.fn.errcheck = errcheck
 
     def __get__(self, obj, objtype=None):
         if not obj._geom:
Index: wkb.py
===================================================================
--- wkb.py	(revision 1203)
+++ wkb.py	(working copy)
@@ -55,11 +55,11 @@
     """
     func = lgeos.GEOSGeomToWKB_buf
     size = c_int()
-    def errcheck(result, func, argtuple):
-        retval = string_at(result, size.value)[:]
-        free(result)
-        return retval
-    func.errcheck = errcheck
+#    def errcheck(result, func, argtuple):
+#        retval = string_at(result, size.value)[:]
+#        free(result)
+#        return retval
+#    func.errcheck = errcheck
     return func(ob._geom, byref(size))
 
 def dump(ob, fp):
@@ -75,4 +75,4 @@
       >>> s.read().encode('hex')
       '010100000000000000000000000000000000000000'
     """
-    fp.write(dumps(ob))
\ No newline at end of file
+    fp.write(dumps(ob))
Index: wkt.py
===================================================================
--- wkt.py	(revision 1203)
+++ wkt.py	(working copy)
@@ -53,12 +53,12 @@
       'POINT (0.0000000000000000 0.0000000000000000)'
     """
     func = lgeos.GEOSGeomToWKT
-    def errcheck(result, func, argtuple):
-        retval = result.value
-        free(result)
-        return retval
-    func.restype = allocated_c_char_p
-    func.errcheck = errcheck
+#    def errcheck(result, func, argtuple):
+#        retval = result.value
+#        free(result)
+#        return retval
+#    func.restype = allocated_c_char_p
+#    func.errcheck = errcheck
     return func(ob._geom)
 
 def dump(ob, fp):
@@ -74,4 +74,4 @@
       >>> s.read()
       'POINT (0.0000000000000000 0.0000000000000000)'
     """
-    fp.write(dumps(ob))
\ No newline at end of file
+    fp.write(dumps(ob))
