Commits

Ronald Oussoren committed d3a5027

Various changes, see ChangeLog for details

Comments (0)

Files changed (22)

+2002-10-30  Ronald Oussoren <oussoren@cistron.nl>
+	* Fix memory corruption bug
+	* Add Obj-C exception handling around calls to ObjC_FindNative,
+	  this avoids an unhandled exception when during:
+	  	help('Foundation')
+	  I didn't add a testcase for this as the above code takes a
+	  _very_ long time to execute.
+	* Some minor code cleanup (mostly removal of print statements)
+	* Reset '__module__' of classes in the __init__.py of AppKit and 
+	  Foundation. help(AppKit) now works (and generates an lot of
+	  output)
+
 2002-10-29  Bill Bumgarner  <bbum@bumbox.local.>
 
 	* Fixed a bug in convenience method that covered objectForKey:.
 	(test_nsdictionary.py), then fixed _convenience.py to fix the
 	problem.
 
+2002-10-28 Ronald Oussoren <oussoren@cistron.nl>
+	* Doc/wrapping.txt: New file containing basic documentation on how
+	  to wrap an Objective-C class library.
+
+2002-10-25 Ronald Oussoren <oussoren@cistron.nl>
+	* Improved inline documentation
+
 2002-10-25  Bill Bumgarner  <bbum@codefab.com>
 
 	* Changed the objc_support.m to compile in the invocation tear
 	* Implemented __ne__ in terms of isEqual_ (not isNotEqual_).
 	* Added unit test that tests that an object is equal to itself.
 
+2002-10-21 Ronald Oussoren <oussoren@cistron.nl>
+	* scripts/buildpkg.py: Import from Python 2.3 CVS, with one minor
+	  bugfix
+	* scripts/make_distrib.py: Create source archive and installer
+	* Modules/objc/register.m: Add signature that is needed to write
+	  system services in Python.
+
 2002-10-18  Bill Bumgarner  <bbum@codefab.com>
 	* Fixed the -dealloc method in OC_PythonDictionary.
 	* Disabled gc in objc's __init__.py (I thought we had done this in

pyobjc/Examples/subclassing-objective-c.py

 print "all->", x.description()
 x=None
 
-#obj.release() 
 obj = None
 print "Done"
+
+objc.recycle_autorelease_pool()

pyobjc/Lib/AppKit/__init__.py

 gl = globals()
 for cls in class_list:
 	gl[cls.__name__] = cls
+	cls.__module__ = 'AppKit'
 
 Foundation._objc.recycle_autorelease_pool()
 

pyobjc/Lib/Foundation/__init__.py

 
 # We use strings to represent selectors, therefore 
 # NSSelectorFromString and NSStringFromSelector are no-ops (for now)
+
 def NSSelectorFromString(aSelectorName):
 	if not isinstance(aSelectorName, str):
 		raise TypeError, "aSelector must be string"
 
 NSStringFromSelector = NSSelectorFromString
 
-
 def NSStringFromClass(aClass):
 	return aClass.__name__
 
 # Define usefull utility methods here
-
 def load_bundle(path):
 	"""
 	Load the specified bundle/framework and return a list of classes 
 	defined in that bundle/framework
 	"""
 	bundle_class = _objc.lookup_class('NSBundle')
-	# print "Bundle-class = ", bundle_class
+
 	bndl = bundle_class.bundleWithPath_(path)
-	# print "Bundle = ", bndl, path
+
 	bndl.load()
+
 	classes = [ cls 
-			for cls in _objc.class_list() 
-			if path == bundle_class.bundleForClass_(cls).bundlePath() ]
+		for cls in _objc.class_list() 
+		if path == bundle_class.bundleForClass_(cls).bundlePath() ]
 	return classes
 
 class_list = load_bundle('/System/Library/Frameworks/Foundation.framework')
 gl = globals()
 for cls in class_list:
 	gl[cls.__name__] = cls
+	cls.__module__ = 'Foundation'
 
 del class_list
 del cls
 		if conversionHelper:
 			return conversionHelper(aPyCollection)
 		raise "UnrecognizedTypeException", "Type %s encountered in python collection;  don't know how to convert." % containerType
-
-# def pythonCollectionFromPropertyList(aPropertyList):
-#	elementClass = aPropertyList.
-#
-# How do I figure out if [aPropertyList isKindOfClass: [NSDictionary class]]??

pyobjc/Lib/Foundation/test/test_nsobject.py

 class TestNSObjectInteraction( unittest.TestCase ):
     def testNSObjectClass( self ):
         self.assert_( NSObject.instancesRespondToSelector_( "description" ), "NSObject class claims it doesn't respond to a selector that it does." )
+        self.assert_( hasattr(NSObject, "description"), "NSObject class claims it doesn't respond to a selector that it does." )
         # self.assert_( NSObject.description(), "NSObject class failed to respond to +description selector." )
 
+
     def testNSObjectInstance( self ):
         instance = NSObject.new()
 

pyobjc/Lib/objc/__init__.py

 """
-new-style pyobjc
+Python <-> Objective-C bridge (PyObjC)
+
+This module defines the core interfaces of the Python<->Objective-C bridge.
 """
 
 ##
 ## Disable gc -- blows up w/Python 2.2
 ##
 import sys
-majorVersion, minorVersion, minorDotVersion, None, None = sys.version_info
-if majorVersion is 2 and minorVersion is 2:
+if sys.version_info[:3] == (2,2,0):
 	import gc
 	gc.disable()
 
+# Aliases for some common Objective-C constants
+import __builtin__
+if hasattr(__builtin__, 'True'):
+	YES=True
+	NO=False
+else:
+	YES=1
+	NO=0
+nil=None
+
 from _objc import *
 from _objc import __version__
 
-
-
 # Import values used to define signatures
 import _objc
 gl = globals()
 for nm in [ x for x in dir(_objc) if x.startswith('_C_') ]:
 	gl[nm] = getattr(_objc, nm)
-del gl, nm, _objc
-
-
+del gl, nm, _objc, x
 
 
 #
 #
 # These 5 are documented in Apple's Objective-C book, in theory these
 # are the only methods that transfer ownership.
-ALLOCATOR_METHODS['alloc'] = 1
-ALLOCATOR_METHODS['allocWithZone:'] = 1
-ALLOCATOR_METHODS['copy'] = 1
-ALLOCATOR_METHODS['copyWithZone:'] = 1
-ALLOCATOR_METHODS['mutableCopyWithZone:'] = 1
+#
+def register_allocator_selector(selector):
+	"""
+	register 'selector' as a method that transfers ownership of the 
+	returned object to the caller. 
+	
+	This information is used by the proxy code to correctly maintain 
+	reference counts. It is highly unlikely that this function should
+	be called outside of the 'objc' module.
+	"""
+	ALLOCATOR_METHODS[selector] = 1
+
+register_allocator_selector('alloc')
+register_allocator_selector('allocWithZone:')
+register_allocator_selector('copy')
+register_allocator_selector('copyWithZone:')
+register_allocator_selector('mutableCopyWithZone:')
 
 
 
 class _runtime:
 	"""
 	Backward compatibility interface.
+
+	This class provides (partial) support for the interface of 
+	older versions of PyObjC.
 	"""
 	def __getattr__(self, name):
 		if name == '__objc_classes__':
 		return lookup_class(name)
 
 	def __eq__(self, other):
-		if self is other:
-			return 1
-		return 0
+		return self is other
 
 	def __repr__(self):
 		return "objc.runtime"
 runtime = _runtime()
+del _runtime
 
-# Outlets in Interface Builder are instance variables
+#
+# Interface builder support.
+#
 IBOutlet = ivar
 
-# Signature for an action in Interface Builder
 def IBAction(func):
+	"""
+	Return an Objective-C method object that can be used as an action
+	in Interface Builder.
+	"""
 	return selector(func, signature="v@:@")
 
-# Aliases for Objective-C lovers...
-YES=1
-NO=0
-nil=None
 
-import _convenience
+
+from _convenience import CONVENIENCE_METHODS, CLASS_METHODS
 
 # Some special modules needed to correctly wrap all
 # methods in the Foundation framework. Doing it here
 # - We want the resources directory to be on the python search-path
 # - It must be at the start of the path
 # - The CWD must not be on the path
-b = lookup_class('NSBundle').mainBundle()
-if b:
-	import sys
-	sys.path.insert(0, '%s/Contents/Resources'%str(b.bundlePath()))
-	try:
-		del sys.path[sys.path.index('')]
-	except ValueError:
-		pass
-	del sys
-del b
-
+if 1:
+	b = lookup_class('NSBundle').mainBundle()
+	if b:
+		sys.path.insert(0, '%s/Contents/Resources'%str(b.bundlePath()))
+		try:
+			del sys.path[sys.path.index('')]
+		except ValueError:
+			pass
+	del b
+del sys, __builtin__

pyobjc/Lib/objc/_convenience.py

+"""
+This module implements a callback function that is used by the C code to
+add Python special methods to Objective-C classes with a suitable interface.
 
+This module contains no user callable code.
+
+TODO:
+- Add external interface: Framework specific modules may want to add to this.
+"""
 from objc import set_class_extender, selector
 
 CONVENIENCE_METHODS = {}
-CLASS_METHODS = {}
+
+
+CLASS_METHODS = { }
 
 def add_convenience_methods(super_class, name, type_dict):
+	"""
+	Add additional methods to the type-dict of subclass 'name' of 
+	'super_class'. 
+	
+	CONVENIENCE_METHODS is a global variable containing a mapping from
+	an Objective-C selector to a Python method name and implementation.
+	
+	CLASS_METHODS is a global variable containing a mapping from 
+	class name to a list of Python method names and implementation.
+
+	Matching entries from both mappings are added to the 'type_dict'.
+	"""
 	for sel in type_dict.values():
 		if not isinstance(sel, selector):
 			continue
 # is there to force conversion to type 'bool' on Python releases
 # that have such a type.
 def __contains__(self, elem):
+	print "doesContain_", elem
 	return self.doesContain_(elem) != 0
 def __eq__1(self, other):
 	return self.isEqualTo_(other) != 0

pyobjc/Lib/objc/builder.py

 * the same module should contain function for replacing/enhancing the 
   Info.plist in the generated application.
 * Add compiled version of the extra sources, instead of the sources themselves
+* Add interface to use the python-starter trick as used by the Interface Builder
+  project.
 """
 
 import buildtools

pyobjc/Lib/objc/classnib.py

 This module contains functions and classes for dealing with the classes.nib
 file in a NIB 'file'.
 
-def parse_classes_nib(nibfile):
-	Parse the classes.nib file inside the given NIB file.
+Usage for this module:
+	NIBFILE1 = "MainMenu.nib"
+	NIBFILE2 = "DocumentWindow.nib"
 
-def generate_wrapper_module(outfp, classinfolist):
-	Generate the wrapper module given the class data in one or more
-	NIB files.
+	info1 = parse_classes_nib(NIBFILE1)
+	info2 = parse_classes_nib(NIBFILE2)
+	fp = open('nibclasses.py', 'w')
+	generate_wrapper_module(fp, [info1, info2])
 
+Using the generated module:
+	import nibclasses
 
+	class MyNibDefinedClass (nibclasses.MyNibDefinedClassBase):
+		def someAction_(self, sender):
+			pass
+
+
+The generated module contains base-classes for all classes defined in the
+NIB file. The base class serves as documentation for the list of methods
+that need to be implemented in subclasses, as wel as a way to avoid working
+with explicit method signatures.
 """
 #
 #An example classes.nib:
 
 def parse_classes_nib(nibfile):
 	"""
-	Parse a classes.nib file inside a NIB file.
+	Parse a classes.nib file inside a NIB file. Returns a list of
+	class information.
 	"""
 	import os
 	return ClassNibParser(
 
 	The only public entry points in this class are the contructor and
 	the parse method.
+
+	NOTE: I (Ronald) have not yet found documentation about the format
+	of the classes.nib file. This implementation is based on reading a
+	number of classes.nib files.
 	"""
 
 	def __init__(self, fp):

pyobjc/Modules/objc/OC_PythonDictionary.m

 		return nil;
 	}
 
+	/* PyMapping_GetItemString exists, but no PyMapping_GetItem */
 #if 0
 	v = PyMapping_GetItem([self pyObject], k);
 #else
 		return;
 	}
 
+	/* PyMapping_SetItemString exists, but no PyMapping_SetItem */
 	if (PyDict_SetItem([self pyObject], k, v) < 0) {
 		Py_DECREF(v);
 		Py_DECREF(k);
 	PyObject* keys = PyMapping_Keys([self pyObject]);
 	id result = [OC_PythonArray newWithPythonObject:keys];
 	Py_DECREF(keys);
-	[result retain];
+	[result retain]; /* XXX leaking!!! */
 
 	return [result objectEnumerator];
 }

pyobjc/Modules/objc/OC_PythonObject.m

 
 - (void) doesNotRecognizeSelector:(SEL) aSelector
 {
+	/* FIXME: Just raise the appropriate Foundation exception */
 	ObjCErr_Set(objc_error, "%s does not recognize -%s",
 		[[super description] cString], SELNAME(aSelector));
 	ObjCErr_ToObjC();

pyobjc/Modules/objc/class-builder.m

 	}
 	if (py_class == NULL || !ObjCClass_Check(py_class)) {
 		ObjCErr_Set(objc_internal_error,
-			"Trying to set class to of %s to invalid",
-			objc_class->name);
+			"Trying to set class to of %s to invalid value "
+			"(type %s instead of %s)",
+			objc_class->name, py_class->ob_type->tp_name,
+			ObjCClass_Type.tp_name);
 		return -1;
 	}
 	if (((struct class_wrapper*)objc_class)->python_class != NULL) {
 	}
 	if (class_getInstanceVariable(objc_class, pyobj_ivar) == NULL) {
 		ObjCErr_Set(objc_internal_error, 
-			"Trying to unregister class of non-python %s", 
+			"Trying to unregister class %s, but it is not "
+			"python based", 
 			objc_class->name);
 		return;
 	}
 	if (wrapper->python_class != NULL) {
 		ObjCErr_Set(objc_internal_error,
-			"Trying to unregister objective-C klass %s",
+			"Trying to unregister objective-C class %s, but it "
+			"is already registered with the runtime",
 			objc_class->name);
 		return;
 	}
 		var->ivar_offset = ivar_size;
 		ivar_size += sizeof(void*);
 
+		/* XXX: Make these global lists instead of macros */
+
 #		define META_METH(pyname, selector, types, imp) 		\
 			meth = meta_method_list->method_list + 		\
 				meta_method_list->method_count++;	\
 		class_addMethods(&(new_class->meta_class), meta_method_list);
 	}
 
+	Py_XDECREF(py_superclass);
+
 	/* 
 	 * NOTE: Class is not registered yet, we do that as lately as possible
 	 * because it is impossible to remove the registration from the
 	return (Class)new_class;
 
 error_cleanup:
+	Py_XDECREF(py_superclass);
+
 	if (key_list != NULL) {
 		Py_DECREF(key_list);
 		key_list = NULL;

pyobjc/Modules/objc/class-list.m

 	}
 
 	for (i = 0; i < bufferLen; i++) {
-		PyObject* pyclass = ObjCClass_New(buffer[i]);
+		PyObject* pyclass;
+
+		pyclass = ObjCClass_New(buffer[i]);
 		if (pyclass == NULL) {
 			goto error_cleanup;
 		}
-		if (PyTuple_SetItem(result, i, pyclass) < 0) {
+		if (PyTuple_SET_ITEM(result, i, pyclass) < 0) {
 			Py_DECREF(pyclass);
 			goto error_cleanup;
 		}

pyobjc/Modules/objc/informal-protocol.m

 "\n"
 "This class can be used to specify which methods are supported by an informal\n"
 "protocol. Instances of this type can by used while creating subclasses of \n"
-"objective-C classes to automaticly specify method signatures et.al.\n"
-"\n"
+"objective-C classes to automaticly specify method signatures et.al."
 "");
 
 typedef struct {
 	return (PyObject*)result;
 }
 
+static int proto_traverse(PyObject* self, visitproc visit, void* handle)
+{
+	ObjCInformalProtocol* me = (ObjCInformalProtocol*)self;	
+	int                   err;
+
+	err = visit(me->name, handle);
+	if (err) return err;
+	err = visit(me->selectors, handle);	
+	if (err) return err;
+	return 0;
+}
 
 
 PyTypeObject ObjCInformalProtocol_Type = {
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT,			/* tp_flags */
  	proto_cls_doc,				/* tp_doc */
- 	0,					/* tp_traverse */
+ 	proto_traverse,				/* tp_traverse */
  	0,					/* tp_clear */
 	0,					/* tp_richcompare */
 	0,					/* tp_weaklistoffset */

pyobjc/Modules/objc/module.m

 	return Py_None;
 }
 
+PyDoc_STRVAR(objc_set_class_extender_doc,
+	"set_class_extender(func) -> None\n"
+	"\n"
+	"Register a function that will be called to update the class\n"
+	"dict of new Objective-C classes and class-proxies. This will\n"
+	"replace any existing callback.\n"
+	"The function will be called like this:\n"
+	"\tclass_extender(superclass, class_name, class_dict)\n"
+	"superclass:\n"
+	"  The superclass for the new class, or None if this is the top of\n"
+	"  a class hierarchy.\n"
+	"class_name:\n"
+	"  Name of the new class\n"
+	"class_dict:\n"
+	"  The proposed class dictionary. The callback is supposed to update\n"
+	"  this dictionary.\n"
+	"");
 static PyObject*
 objc_set_class_extender(PyObject* self, PyObject* args, PyObject* kwds)
 {
 }
 
 
+PyDoc_STRVAR(objc_class_list_doc,
+  "class_list() -> [ cls, ...] n"
+  "\n"
+  "Return a list with all Objective-C classes known to the runtime.\n"
+);
+
 static PyObject* 
 objc_class_list(PyObject* self)
 {
 	return ObjC_GetClassList();
 }
 
+PyDoc_STRVAR(set_signature_for_selector_doc,
+	"set_signature_for_selector(class_name, selector, signature) -> None\n"
+	"\n"
+	"Register a replacement signature for a specific selector. This \n"
+	"can be used to provide a more exact signature for a method.\n"
+	"");
 static PyObject* 
 objc_set_signature_for_selector(PyObject* self, PyObject* args, PyObject* kwds)
 {
 
 static PyMethodDef meta_methods[] = {
 	{ "lookup_class", (PyCFunction)objc_lookup_class, METH_VARARGS|METH_KEYWORDS, objc_lookup_class_doc },
-	{ "class_list", (PyCFunction)objc_class_list, METH_NOARGS, ""},
-	{ "set_class_extender", (PyCFunction)objc_set_class_extender, METH_VARARGS|METH_KEYWORDS, ""},
-	{ "set_signature_for_selector", (PyCFunction)objc_set_signature_for_selector, METH_VARARGS|METH_KEYWORDS, "" },
+	{ "class_list", (PyCFunction)objc_class_list, METH_NOARGS, objc_class_list_doc },
+	{ "set_class_extender", (PyCFunction)objc_set_class_extender, METH_VARARGS|METH_KEYWORDS, objc_set_class_extender_doc  },
+	{ "set_signature_for_selector", (PyCFunction)objc_set_signature_for_selector, METH_VARARGS|METH_KEYWORDS, set_signature_for_selector_doc },
 	{ "recycle_autorelease_pool", (PyCFunction)objc_recycle_autorelease_pool, METH_VARARGS|METH_KEYWORDS, objc_recycle_autorelease_pool_doc },
 	{ 0, 0, 0, 0 } /* sentinel */
 };
 	PyType_Ready(&ObjCIvar_Type);
 	PyType_Ready(&ObjCInformalProtocol_Type);
 
-	m = Py_InitModule4("_objc", meta_methods, "metatest-doc", 
+	m = Py_InitModule4("_objc", meta_methods, NULL,
 			NULL, PYTHON_API_VERSION);
 	d = PyModule_GetDict(m);
 

pyobjc/Modules/objc/objc-class.m

 #include "pyobjc.h"
 #include "objc_support.h"
 #include <stddef.h>
-//#include <Foundation/Foundation.h>
+
+PyDoc_STRVAR(class_doc,
+"objc_class(name, bases, dict) -> a new Objective-C class\n"
+"\n"
+"objc_class is the meta-type for Objective-C classes. It should not be\n"
+"necessary to manually create instances of this type, those are \n"
+"created by subclassing and existing Objective-C class.\n"
+"\n"
+"The list of bases must start with an existing Objective-C class, and \n"
+"cannot contain other Objective-C classes. The list may contain\n"
+"informal_interface objects, those are used during the calculation of\n"
+"method signatures and will not be visible in the list of base-classes\n"
+"of the created class."
+);
 
 static int add_class_fields(Class objc_class, PyObject* dict);
 
 		return NULL;
 	}
 	Py_DECREF(item); 
-	Py_INCREF(class);
+	/* Py_INCREF(class); XXX Needed? */
 	return info;
 }
 
 static int 
 objc_class_register(Class objc_class, PyObject* py_class)
 {
+	/* TODO: Also add to 'register_proxy' structure in obc-object.m
+	 * (just in case a class is returned where an 'id' is expected 
+	 * according to the method signature)
+	 */
 	int res;
 	
 	if (class_registry == NULL) {
 	if (res != 0) {
 		abort();
 	}
+	Py_INCREF(py_class);
 	return res;
 }
 
 	PyObject* protocols;
 	PyObject* real_bases;
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwds, "sOO:meta_new",
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "sOO:__new__",
 			keywords, &name, &bases, &dict)) {
 		return NULL;
 	}
 		return NULL;
 	}
 	Py_DECREF(args);
-	Py_DECREF(real_bases);
+	//Py_DECREF(real_bases);
 	args = NULL;
 	real_bases = NULL;
 
 	if (cls) {
 		snprintf(buffer, sizeof(buffer), 
 			"<objective-c class %s at %p>", 
-			cls->name, obj);
+			cls->name, cls);
 	} else {
 		snprintf(buffer, sizeof(buffer),
 			"%s", "<objective-c class NIL>");
 
 	/* Try to find the method anyway */
 	PyErr_Clear();
-	result = ObjCSelector_FindNative(self, PyString_AsString(name));
+	NS_DURING
+		result = ObjCSelector_FindNative(self, PyString_AsString(name));
+	NS_HANDLER
+		ObjCErr_FromObjC(localException);
+		result = NULL;
+	NS_ENDHANDLER
+
 	if (result != 0) {
 		int res = PyDict_SetItem(((PyTypeObject*)self)->tp_dict, name, result);
 		ObjCNativeSelector* x = (ObjCNativeSelector*)result;
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
 	Py_TPFLAGS_DEFAULT,			/* tp_flags */
- 	0,					/* tp_doc */
+ 	class_doc,				/* tp_doc */
  	0,					/* tp_traverse */
  	0,					/* tp_clear */
 	0,					/* tp_richcompare */
 		Py_INCREF(result);
 		return result;
 	}
+	PyErr_Clear();
 
 	dict = PyDict_New();
 	if (add_class_fields(objc_class, dict) < 0)  {
 	info->method_magic = objc_methodlist_magic(objc_class);
 
 	objc_class_register(objc_class, result);
-	Py_INCREF(result);
 
 	return result;
 }

pyobjc/Modules/objc/objc-object.m

 #include "pyobjc.h"
 #include <stddef.h>
 
+#import <Foundation/NSString.h> /*XXX*/
+
 /*
  * We use weakreferences to make sure that every objective-C object has 
  * at most one python proxy. This allows users to use the 'is' operator
 	if (result) return result;
 
 	PyErr_Clear();
-	result = ObjCSelector_FindNative(obj, PyString_AsString(name));
+	NS_DURING
+		result = ObjCSelector_FindNative(obj, PyString_AsString(name));
+	NS_HANDLER
+		ObjCErr_FromObjC(localException);
+		result = NULL;
+	NS_ENDHANDLER
 
 	return result;
 }

pyobjc/Modules/objc/objc_support.m

       break;
 
     default:
-      {
-      /* XXX: Ronald: Why are GNU and Apple runtimes treated differently? */
-#ifdef GNU_RUNTIME
-        [NSException raise:NSInternalInconsistencyException 
-                     format:@"unhandled value type (%c|%d|%s)", *type, *type, type];
-#else
-#define ERRMSG "pythonify_c_value: unhandled value type (%c|%d|%s)"
-        char msg[sizeof ERRMSG];
-        sprintf (msg, ERRMSG, *type, *type, type);
-        PyErr_SetString (objc_error, msg);
-#undef ERRMSG
-#endif
+	ObjCErr_Set(objc_error, 
+		"pythonify_c_value: unhandled value type (%c|%d|%s)",
+		*type, *type, *type);
         break;
-      }
     }
 
   return retobject;
 #endif
 
 /* This is used as an array of pointers: both the memory for the array
-   and that for each array's slot is dinamically allocated with malloc().
+   and that for each array's slot is dynamically allocated with malloc().
    We use it when we have to give an ObjC method a pointer to some datum:
    since from the Python point of view we always work on values, not pointers,
    when an ObjC does actually want a pointer, we allocate memory in the
 	ObjCNativeSelector* meth = (ObjCNativeSelector*)aMeth;
 	PyObject*	  objc_result = NULL;
 	PyObject*	  result = NULL;
-	id		  self_obj = NULL;
+	id		  self_obj = nil;
+	id                nil_obj = nil;
 
 	methinfo = [NSMethodSignature signatureWithObjCTypes:meth->sel_signature];
 	objc_argcount = [methinfo numberOfArguments];
 	}
 
 	[inv setTarget:self_obj];
-#if 0
-	[inv setArgument:&self_obj atIndex:0];
-#endif
-
 	[inv setSelector:meth->sel_selector];
-#if 0
-	[inv setArgument:&(meth->sel_selector) atIndex:1];
-#endif
 
 	py_arg = 0;
 	for (i = 2; i < objc_argcount; i++) {
 #if 1
 	self_obj = nil;
 	if (*[methinfo methodReturnType] == _C_ID) {
-		[inv setReturnValue:&self_obj];
+		[inv setReturnValue:&nil_obj];
 	}
-	[inv setTarget:self_obj];
-	[inv setArgument:&self_obj atIndex:0];
+	[inv setTarget:nil];
 #endif
-
 	[inv release];
-	[methinfo release];
 	inv = nil;
 
 	PyMem_Free(argbuf);
 error_cleanup:
 	if (inv) {
 		self_obj = nil;
+#if 1
 		if (*[methinfo methodReturnType] == _C_ID) {
 			[inv setReturnValue:&self_obj];
 		}
-		[inv setTarget:self_obj];
-		[inv setArgument:&self_obj atIndex:0];
+#endif
+		[inv setTarget:nil];
 		[inv release];
 		inv = nil;
 	}

pyobjc/Modules/objc/objc_util.h

 
 char* ObjC_strdup(const char* value);
 
+#if 0 /* Multithread support */
+
+void ObjC_AcquireGIL(void);
+void ObjC_ReleaseGIL(void);
+
+#define OBJC_BEGIN_OBJC_CALL { ObjC_ReleaseGIL();
+#define OBJC_END_OBJC_CALL ObjC_AcquireGIL(); }
+#define OBJC_BEGIN_PYTHON_CALL { ObjC_AcquireGIL();
+#define OBJC_END_PYTHON_CALL ObjC_ReleaseGIL(); }
+
+#else 
+
+#define OBJC_BEGIN_OBJC_CALL {
+#define OBJC_END_OBJC_CALL }
+
+#define OBJC_BEGIN_PYTHON_CALL {
+#define OBJC_END_PYTHON_CALL }
+
+#endif /* No multithread support */
+
 #endif /* OBJC_UTIL */

pyobjc/Modules/objc/objc_util.m

 		return -1;
 	}
 	Py_DECREF(args);
-	Py_DECREF(super_class);
 
 	return 0;
 }
 	result[len] = 0;
 	return result;
 }
+
+#if 0 /* Multithreading support */
+
+/*
+ * Initial support for multithread access to the bridge. Code is completely
+ * untested (even never compiled). Based on a hint by Jack Jansen.
+ *
+ * What needs to be done in the rest of the code: 
+ * - ObjC_ReleaseGIL() ... ObjC_AcquireGIL() around calls to Obj-C
+ * - ObjC_AcquireGIL() ... ObjC_ReleaseGIL() around calls to Python
+ * These should be wrapped into macros (like 'Py_BEGIN_ALLOW_THREADS')
+ * 
+ * OBJC_BEGIN_OBJC_CALL
+ * 	[objc doit]
+ * OBJC_END_OBJC_CALL
+ *
+ * And:
+ * OBJC_BEGIN_PYTHON_CALL
+ * 	PyList_GetItem([self pyObject], 3)
+ * 	...
+ * OBJC_END_PYTHON_CALL
+ */
+static id  threadKey = @"PyObjCInterpreterState";
+static int multiThreaded = 1;
+static PyInterpreterState* interpreterState = NULL;
+
+void  ObjC_ReleaseGIL(void)
+{
+	NSMutableDictionary* td = [[NSThread currentThread] threadDictionary];
+	PyThreadState* save;
+
+	if (interpreterState == NULL) {
+		interpreterState = PyThreadState_Get()->interp;
+	}
+
+	save = PyEval_SaveThread();
+
+	[td setObject:save forKey:threadKey];
+}
+
+void ObjC_AcquireGIL(void)
+{
+	PyThreadState* save;
+
+	save = [td objectForKey:threadKey];
+
+	if (save == nil) {
+		/* No thread state, make a new one */
+		PyEval_AcquireLock();
+		save = PyThreadState_New(interpreter);
+		PyThreadState_Swap(save);
+	} else {
+		PyEval_RestoreThread(save);
+	}
+}
+
+#endif /* Multithreading support */

pyobjc/Modules/objc/selector.m

 	return PyString_FromString(self->sel_signature);
 }
 
-PyDoc_STRVAR(base_selector_doc, 
-"Objective-C selector for a method\n");
+PyDoc_STRVAR(base_selector_doc, "Objective-C name for a method\n");
 static PyObject*
 base_selector(ObjCSelector* self, void* closure)
 {
 	object->ob_type->tp_free(object);
 }
 
-
+/* Ronald: This is probably a bit too much documentation... */
 PyDoc_STRVAR(base_selector_type_doc,
-"selector(function, [, signature] [, selector] [, class_method=0] "
-"[, return_type] [, argument_types] [, required=True]) -> selector\n"
+"selector(function, [, signature] [, selector] [, class_method=0]\n"
+"    [, return_type] [, argument_types] [, required=True]) -> selector\n"
 "\n"
-"signature is an objective-C style signature string. return_type and \n"
-"argument_types specify the same information using a PyArg_ParseTuple style \n"
-"format\n\n"
-"The default for selector: function.__name__.replace('_', ':')\n"
-"The default for signature is that for a function that returns an object and \n"
-"takes objects as argument (one for every argument of 'function'.\n"
-"The 'required' argument is only used with informal protocols."
+"Return an Objective-C method from a function. The other arguments \n"
+"specify attributes of the Objective-C method.\n"
+"\n"
+"function:\n"
+"  A function object with at least one argument. The first argument will\n"
+"  be used to pass 'self'. This argument may be non when defineing an \n"
+"  informal_protocol object.\n"
+"selector:\n"
+"  The name of the Objective-C method. The default value of this\n"
+"  attribute is the name of the function, with all underscores replaced\n"
+"  by colons.\n"
+"signature:\n"
+"  Method signature for the Objective-C method. This should be a raw \n"
+"  Objective-C method signature, including specifications for 'self' and\n"
+"  '_cmd'. The default value a signature that describes a method with \n"
+"  arguments of type 'id' and a return-value of the same type.\n"
+"argument_types, return_type:\n"
+"  Alternative method for specifying the method signature. Return_type is\n"
+"  return type and argument_types describes the list of arguments. The \n"
+"  return_type is optional and defaults to 'void' (e.g. no return value).\n"
+"  Both are specified using a subset of the Py_BuildValue syntax:\n"
+"  - s, z, S: an NSString (id)\n"
+"  - b: a byte (char)\n"
+"  - h: a short integer (short int)\n"
+"  - i: an integer (int)\n"
+"  - l: a long integer (long int)\n"
+"  - c: a single character (char)\n"
+"  - f: a single precision float (float)\n"
+"  - d: a double precision float (double)\n"
+"  - O: any object (id)\n"
+"  It is not allowed to specify both 'argument_types' and 'signature'\n"
+"class_method:\n"
+"  True if the method is a class method, false otherwise"
+"required:\n"
+"  True if this is a required method in an informal protocol, false \n"
+"  otherwise. The default value is 'True'. This argument is only used\n"
+"  when defining an 'informal_protocol' object.\n"
 );
 PyTypeObject ObjCSelector_Type = {
 	PyObject_HEAD_INIT(&PyType_Type)
 
 	if (res && ObjCObject_Check(res) && self->sel_allocator) {
 		/* Ownership transfered to us, but 'execute' method has
-		 * increased retainCount, the retainCount is now one to high
+		 * increased retainCount, the retainCount is now one too high
 		 */
-    // [ObjCObject_GetObject(res) release];
-    ;
+		id obj = ObjCObject_GetObject(res);
+    		/*[ObjCObject_GetObject(res) release]; XXX */
 	}
 	return res;
 }
 	return (PyObject*)result;
 }
 
-PyDoc_STRVAR(native_class_doc, 
-"Objective-C Class that defines a method\n");
+PyDoc_STRVAR(native_class_doc, "Objective-C Class that defines the method\n");
 static PyObject*
 native_class(ObjCNativeSelector* self, void* closure)
 {
 	0,					/* tp_iternext */
 	0,					/* tp_methods */
 	0,					/* tp_members */
-	&native_getset,				/* tp_getset */
+	native_getset,				/* tp_getset */
 	&ObjCSelector_Type,			/* tp_base */
 	0,					/* tp_dict */
 	(descrgetfunc)objcsel_descr_get,	/* tp_descr_get */
 	if (ObjCClass_Check(self)) {
 		Class cls = ObjCClass_GetClass(self);
 
+		if (!cls) {
+			ObjCErr_Set(PyExc_AttributeError,
+				"No attribute %s", name);
+			return NULL;
+		}
+
+		if (strcmp(cls->name, "NSProxy") == 0) {
+			if (sel == @selector(methodSignatureForSelector:)) {
+				ObjCErr_Set(PyExc_AttributeError,
+					"Cannot access NSProxy.%s", name);
+				return NULL;
+			}
+		}
+
 		if ([cls instancesRespondToSelector:sel]) {
 			methsig = [cls instanceMethodSignatureForSelector:sel];
 			return ObjCSelector_NewNative(cls, sel, 

pyobjc/Modules/objc/super-call.m

 
 	r = find_signature(signature);
 
-	if (r) return r->call_to_python;
-
-	printf("No IMP for signature %s\n", signature);
-	return NULL;
+	return r?r->call_to_python:NULL;
 }
 
 IMP ObjC_FindIMP(Class class, SEL sel)
 
 	generic = find_signature(ObjCSelector_Signature(objc_sel));
 	if (generic) {
-		if (PyErr_Occurred()) {
-			PyErr_Print();
-		}
 		return generic->call_to_python;
 	}
-	printf("No IMP for selector %s in %s\n", SELNAME(sel), class->name);
 	return NULL;
 }
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.