Commits

Ronald Oussoren committed 7fffd73

A fist cut at teaching PyObjC to do weaklinking, that is run on Panther even
when build on Tiger.

Comments (0)

Files changed (9)

Lib/Foundation/test/test_nstimer.py

         NSRunLoop.currentRunLoop().addTimer_forMode_(
                 timer, NSDefaultRunLoopMode)
         NSRunLoop.currentRunLoop().runUntilDate_(
-                NSDate.dateWithTimeIntervalSinceNow_(0.2))
+                NSDate.dateWithTimeIntervalSinceNow_(0.5))
         timer.invalidate()
         self.assertEquals(obj.fireCount, 1)
 

Modules/AppKit/_AppKit.m

 		Py_DECREF(o);
 	}
 	Py_DECREF(v);
+
+	PyObjC_PerformWeaklinking(d, gWeaklink);
 }

Modules/Foundation/_Foundation.m

 		Py_DECREF(o);
 	}
 	Py_DECREF(v);
+
+	PyObjC_PerformWeaklinking(d, gWeaklink);
 }

Modules/objc/pyobjc-api.h

 
 #import <Foundation/NSException.h>
 
+struct PyObjC_WeakLink {
+	const char* name;
+	void (*func)(void);
+};
+
+
 /* threading support */
 #define PyObjC_DURING \
 		Py_BEGIN_ALLOW_THREADS \
  * - Version 13 adds PyObjCCreateOpaquePointerType
  * - Version 14 adds PyObjCObject_NewTransient, PyObjCObject_ReleaseTransient
  * - Version 15 changes the interface of PyObjCObject_New
+ * - Version 16 adds PyObjC_PerformWeaklinking
  */
-#define PYOBJC_API_VERSION 15
+#define PYOBJC_API_VERSION 16
 
 #define PYOBJC_API_NAME "__C_API__"
 
 
 	/* void PyObjCObject_ReleaseTransient(PyObject* proxy, int cookie); */
 	void (*releasetransient)(PyObject* proxy, int cookie);
-	
+
+	void (*doweaklink)(PyObject*, struct PyObjC_WeakLink*);
 	
 };
 
 #define PyObjCCreateOpaquePointerType (PyObjC_API->pointer_type_new)
 #define PyObjCObject_NewTransient (PyObjC_API->newtransient)
 #define PyObjCObject_ReleaseTransient (PyObjC_API->releasetransient)
+#define PyObjC_PerformWeaklinking (PyObjC_API->doweaklink)
 
 #ifndef PYOBJC_METHOD_STUB_IMPL
 

Modules/objc/pyobjc-api.m

 #undef PyObjCObject_GetObject
 #endif
 
+static void do_weaklink(PyObject* module_dict, struct PyObjC_WeakLink* funcs)
+{
+	while (funcs->name) {
+		if (!funcs->func) {
+			if (PyDict_DelItemString(
+					module_dict,
+					funcs->name) == -1) {
+				PyErr_Clear();
+			}
+		}
+		funcs++;
+	}
+}
+
 static int obj_is_uninitialized(PyObject* object)
 {
 	if (!PyObjCObject_Check(object)) {
 	PyObjCCreateOpaquePointerType, /* pointer_type_new */
 	PyObjCObject_NewTransient,	/* newtransient */
 	PyObjCObject_ReleaseTransient,  /* releasetransient */
+	do_weaklink,			/* doweaklink */
 };
 
 int PyObjCAPI_Register(PyObject* module)
 
 An overview of the relevant changes in new, and older, releases.
 
-Version 1.3.8 (????-??-??)
+Version 1.4 (????-??-??)
 --------------------------
 
+- It is now possible to build PyObjC on Tiger and use the resulting binaries
+  on Panther. The binaries still include wrappers for all functions on Tiger.
+
 - Classes whose name starts with and underscore are no longer imported when
   using ``objc.loadBundle``. They are still available using 
   ``objc.lookUpClass``.

Scripts/CodeGenerators/cocoa_generator.py

         'NSString* NSLocalizedStringFromTableInBundle(NSString* key, NSString* tableName, NSString* comment, NSBundle* bunlde);',
     ])
     func_builder.gen_method_table_entries(fd, funcs + funcs2 + funcs3)
+    func_builder.gen_method_weaklink_table(fd, funcs + funcs2)
     fd = None
     for s in structs:
         del func_builder.SIMPLE_TYPES[s]
         ])
 
     func_builder.gen_method_table_entries(fd, funcs + funcs2)
+    func_builder.gen_method_weaklink_table(fd, funcs + funcs2)
     for s in structs:
         del func_builder.SIMPLE_TYPES[s]
 
     func_builder.TYPE_ALIASES['OSType'] = 'int'
     funcs = func_builder.process_list(fd , file('build/codegen/QTKit.prototypes'))
     func_builder.gen_method_table_entries(fd, funcs)
+    func_builder.gen_method_weaklink_table(fd, funcs)
     fd.close()
 
 

Scripts/CodeGenerators/enum_generator.py

     for ln in open(fname, 'r'):
         if ln.startswith('#warning') and 'adjust your header import' in ln:
             return 1
+        if ln.startswith('#warning') and 'This header file is obsolete' in ln:
+            return 1
+        if ln.startswith('#warning') and 'The API is this header is obsolete' in ln:
+            return 1
     return 0
 
 def generate(dirname, fn = None, filter = lambda x: 1, ignore_files=(), emit_imports=1, emit_header=1, emit_footer=1):

Scripts/CodeGenerators/func_builder.py

             fp.write('\t{ "%(funcname)s", (PyCFunction)objc_%(funcname)s, METH_VARARGS|METH_KEYWORDS, "%(funcproto)s" }, \\\n'%{'funcname':f[0], 'funcproto':f[1]})
         fp.write("\t/* END */\n")
 
+def gen_method_weaklink_table(fp, funcs):
+    fp.write(
+        'struct PyObjC_WeakLink gWeaklink[] = {\n'
+    )
+
+    for f in funcs:
+        if f[0] is None: continue
+        fp.write('\t{ "%(funcname)s", (void(*)(void))&%(funcname)s },\n'%(
+            { 'funcname': f[0] }))
+
+    fp.write('\t{ NULL, NULL }\n')
+    fp.write('};\n')
 
 if __name__ == "__main__":
     import sys
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.