Commits

Ronald Oussoren committed a275c4a

Don't create new classes in the ObjC runtime for the Python classes that represent CoreFoundation types.
This should make it easier to have PyObjC and RubyCocoa in a single application.

  • Participants
  • Parent commits 8ed6ff9
  • Branches pyobjc2

Comments (0)

Files changed (4)

pyobjc-core/Modules/objc/corefoundation.h

 #ifndef PyObjC_COREFOUNDATION_H
 #define PyObjC_COREFOUNDATION_H
 
+extern PyObject* PyObjC_NSCFTypeClass;
+
 extern int PyObjCCFType_Setup(void);
 extern PyObject* PyObjCCFType_New(char* name, char* encoding, CFTypeID typeID);
 extern PyObject* PyObjCCF_NewSpecial(char* encoding, void* datum);

pyobjc-core/Modules/objc/corefoundation.m

 #include <CoreFoundation/CoreFoundation.h>
 
 static PyObject* gTypeid2class = NULL;
-static PyObject* gBaseClass = NULL;
+PyObject* PyObjC_NSCFTypeClass = NULL;
 
 static PyObject*
 cf_repr(PyObject* self)
 
 	bases = PyTuple_New(1);
 
-	PyTuple_SET_ITEM(bases, 0, gBaseClass);
-	Py_INCREF(gBaseClass);
+	PyTuple_SET_ITEM(bases, 0, PyObjC_NSCFTypeClass);
+	Py_INCREF(PyObjC_NSCFTypeClass);
 
 	args = PyTuple_New(3);
 	PyTuple_SetItem(args, 0, PyString_FromString(name));
 	((PyTypeObject*)result)->tp_str = cf_repr;
 
 	info = (PyObjCClassObject*)result;
-	info->class = PyObjCClass_GetClass(gBaseClass);
+	info->class = PyObjCClass_GetClass(PyObjC_NSCFTypeClass);
 	info->sel_to_py = NULL;
 	info->method_magic = 0;
 	info->dictoffset = 0;
 			"Cannot locate NSCFType");
 		return -1;
 	}
-	gBaseClass = PyObjCClass_New(cls);
-	if (gBaseClass == NULL) {
+	PyObjC_NSCFTypeClass = PyObjCClass_New(cls);
+	if (PyObjC_NSCFTypeClass == NULL) {
 		return -1;
 	}
 

pyobjc-core/Modules/objc/objc-class.m

 	PyObject* useKVOObj;
 	Ivar var;
 	PyObject* protectedMethods = NULL;
+	BOOL      isCFProxyClass = NO;
 
 	if (!PyArg_ParseTupleAndKeywords(args, kwds, "sOO:__new__",
 			keywords, &name, &bases, &dict)) {
 		return NULL;
 	}
 
+	if (py_super_class == PyObjC_NSCFTypeClass) {
+		/* A new subclass of NSCFType 
+		 * -> a new proxy type for CoreFoundation classes
+		 */
+		isCFProxyClass = YES;
+	}
+
 	if (!PyObjCClass_Check(py_super_class)) {
 		PyErr_SetString(PyExc_TypeError, 
 				"first base class must "
 		return NULL;
 	}
 
-	/* First generate the objective-C class. This may change the
-	 * class dict.
-	 */
-	objc_class = PyObjCClass_BuildClass(super_class, protocols, name, dict, metadict);
-	if (objc_class == NULL) {
-		Py_DECREF(protocols);
-		Py_DECREF(metadict);
-		Py_DECREF(real_bases);
-		return NULL;
+	if (isCFProxyClass) {
+		objc_class = nil;
+	} else {
+		/* First generate the objective-C class. This may change the
+		 * class dict.
+		 */
+		objc_class = PyObjCClass_BuildClass(super_class, protocols, name, dict, metadict);
+		if (objc_class == NULL) {
+			Py_DECREF(protocols);
+			Py_DECREF(metadict);
+			Py_DECREF(real_bases);
+			return NULL;
+		}
+
+		/* PyObjCClass_BuildClass may have changed the super_class */
+		super_class = class_getSuperclass(objc_class);
+		py_super_class = PyObjCClass_New(super_class);
+		if (py_super_class == NULL) {
+			(void)PyObjCClass_UnbuildClass(objc_class);
+			Py_DECREF(protocols);
+			Py_DECREF(real_bases);
+			Py_DECREF(metadict);
+			return NULL;
+		} else {
+			PyObjCClass_CheckMethodList(py_super_class, 1);
+		}
+
+		Py_DECREF(PyList_GET_ITEM(real_bases, 0));
+		PyList_SET_ITEM(real_bases, 0, py_super_class);
 	}
 
-	/* PyObjCClass_BuildClass may have changed the super_class */
-	super_class = class_getSuperclass(objc_class);
-	py_super_class = PyObjCClass_New(super_class);
-	if (py_super_class == NULL) {
-		(void)PyObjCClass_UnbuildClass(objc_class);
-		Py_DECREF(protocols);
-		Py_DECREF(real_bases);
-		Py_DECREF(metadict);
-		return NULL;
-	} else {
-		PyObjCClass_CheckMethodList(py_super_class, 1);
-	}
-
-	Py_DECREF(PyList_GET_ITEM(real_bases, 0));
-	PyList_SET_ITEM(real_bases, 0, py_super_class);
-
 	v = PyList_AsTuple(real_bases);
 	if (v == NULL) {
-		(void)PyObjCClass_UnbuildClass(objc_class);
+		if (objc_class != nil) {
+			(void)PyObjCClass_UnbuildClass(objc_class);
+		}
 		Py_DECREF(metadict);
 		Py_DECREF(protocols);
 		Py_DECREF(real_bases);
 		PyErr_Clear();
 	} else {
 		Py_INCREF(delmethod);
-		if (PyDict_DelItemString(dict, "__del__") < 0) {
-			(void)PyObjCClass_UnbuildClass(objc_class);
+
+		if (isCFProxyClass) {
+			PyErr_SetString(PyObjCExc_Error,
+			    "cannot define __del__ on subclasses of NSCFType");
 			Py_DECREF(protocols);
 			Py_DECREF(real_bases);
 			Py_DECREF(metadict);
 			return NULL;
+		} else {
+			if (PyDict_DelItemString(dict, "__del__") < 0) {
+				if (objc_class != nil) {
+					(void)PyObjCClass_UnbuildClass(objc_class);
+				}
+				Py_DECREF(protocols);
+				Py_DECREF(real_bases);
+				Py_DECREF(metadict);
+				return NULL;
+			}
 		}
 	}
 
 	 */
 	old_dict = PyDict_Copy(dict);
 	if (old_dict == NULL) {
-		(void)PyObjCClass_UnbuildClass(objc_class);
+		if (objc_class != nil) {
+			(void)PyObjCClass_UnbuildClass(objc_class);
+		}
 		Py_DECREF(protocols);
 		Py_DECREF(real_bases);
 		Py_DECREF(metadict);
 		return NULL;
 	}
-
-
 		
-	if (add_convenience_methods(objc_class, dict) < 0) {
-		(void)PyObjCClass_UnbuildClass(objc_class);
-		Py_DECREF(old_dict);
-		Py_DECREF(protocols);
-		Py_DECREF(real_bases);
-		Py_DECREF(metadict);
-		return NULL;
+	if (objc_class != nil) {
+		if (add_convenience_methods(objc_class, dict) < 0) {
+			(void)PyObjCClass_UnbuildClass(objc_class);
+			Py_DECREF(old_dict);
+			Py_DECREF(protocols);
+			Py_DECREF(real_bases);
+			Py_DECREF(metadict);
+			return NULL;
+		}
 	}
 
-	PyTypeObject* metatype = PyObjCClass_NewMetaClass(objc_class);
-	if (metatype == NULL) {
-		Py_DECREF(old_dict);
-		Py_DECREF(protocols);
-		Py_DECREF(real_bases);
-		Py_DECREF(metadict);
-		return NULL;
-	}
-	if (PyDict_Update(metatype->tp_dict, metadict) == -1) {
-		Py_DECREF(old_dict);
-		Py_DECREF(protocols);
-		Py_DECREF(real_bases);
-		Py_DECREF(metadict);
-		return NULL;
+
+
+	PyTypeObject* metatype;
+	if (objc_class != nil) {
+		metatype = PyObjCClass_NewMetaClass(objc_class);
+		if (metatype == NULL) {
+			Py_DECREF(old_dict);
+			Py_DECREF(protocols);
+			Py_DECREF(real_bases);
+			Py_DECREF(metadict);
+			return NULL;
+		}
+		if (PyDict_Update(metatype->tp_dict, metadict) == -1) {
+			Py_DECREF(old_dict);
+			Py_DECREF(protocols);
+			Py_DECREF(real_bases);
+			Py_DECREF(metadict);
+			return NULL;
+		}
+	} else {
+		metatype = PyObjC_NSCFTypeClass->ob_type;
 	}
 	Py_DECREF(metadict); metadict = NULL;
 
 	Py_DECREF(protocols);
 	protocols = NULL;
 
-	/* Register the proxy as soon as possible, we can get initialize calls
-	 * very early on with the ObjC 2.0 runtime.
-	 */
-	PyObjC_RegisterPythonProxy(objc_class, res);
+	if (objc_class != nil) {
+		/* Register the proxy as soon as possible, we can get 
+		 * initialize calls very early on with the ObjC 2.0 runtime.
+		 */
+		PyObjC_RegisterPythonProxy(objc_class, res);
 
-	if (objc_class_register(objc_class, res) < 0) {
-		PyObjC_UnregisterPythonProxy(objc_class, res);
-		Py_DECREF(res);
-		Py_DECREF(old_dict);
-		(void)PyObjCClass_UnbuildClass(objc_class);
-		return NULL;
+		if (objc_class_register(objc_class, res) < 0) {
+			PyObjC_UnregisterPythonProxy(objc_class, res);
+			Py_DECREF(res);
+			Py_DECREF(old_dict);
+			(void)PyObjCClass_UnbuildClass(objc_class);
+			return NULL;
+		}
+
+		PyObjCClass_FinishClass(objc_class);
 	}
 
-	PyObjCClass_FinishClass(objc_class);
 
 	info = (PyObjCClassObject*)res;
 	info->class = objc_class;
+	if (isCFProxyClass) {
+		info->class = PyObjCClass_GetClass(PyObjC_NSCFTypeClass);
+	}
 	info->sel_to_py = NULL; 
 	info->method_magic = PyObjC_methodlist_magic(objc_class);
 	info->dictoffset = 0;

pyobjc-core/NEWS.txt

 
 - BUGFIX: It is now possible to override ``respondsToSelector:`` in Python.
 
+- BUGFIX: The wrappers for CoreFoundation types no longer create a new type in the Objective-C runtime,
+  that type wasn't used anywhere and was an unwanted side-effect of how CoreFoundation types are wrapped.
+
 
 Version 2.0.1 (...)
 -------------------