Commits

Ronald Oussoren committed 0467def

Always use an NSString as helper for OC_PythonUnicode

* When sizeof(Py_UNICODE) == sizeof(unichar) we could work without the NSString,
but for some reason that causes problems with some CFString APIs

* Provide a number of __realObject__ implementations to optimize the
creation of the NSString: don't copy actual string data unless
really necessary

* This checkin also adds caching for selector lookups, should slightly
improve performance

This also add some other changes to reduce the amount of warnings with
newer versions of clang.

  • Participants
  • Parent commits df792c7

Comments (0)

Files changed (19)

pyobjc-core/Modules/objc/OC_PythonArray.h

  *
  * Caller must own the GIL
  */
-+ depythonifyObject:(PyObject*)object;
++(OC_PythonArray*)depythonifyObject:(PyObject*)object;
 
 
 /*!
  *
  * Caller must own the GIL.
  */
-+ arrayWithPythonObject:(PyObject*)value;
++(OC_PythonArray*)arrayWithPythonObject:(PyObject*)value;
 
 /*!
  * @method initWithPythonObject:
 
 /* These two are only present to *disable* coding, not implement it */
 - (void)encodeWithCoder:(NSCoder*)coder;
-- initWithCoder:(NSCoder*)coder;
+- (id)initWithCoder:(NSCoder*)coder;
 
 @end

pyobjc-core/Modules/objc/OC_PythonData.h

  *
  * Caller must own the GIL.
  */
-+ dataWithPythonObject:(PyObject*)value;
++(OC_PythonData*)dataWithPythonObject:(PyObject*)value;
 
 /*!
  * @method initWithPythonObject:
  *
  * Caller must own the GIL.
  */
-- initWithPythonObject:(PyObject*)value;
+-(OC_PythonData*)initWithPythonObject:(PyObject*)value;
 
 /*!
  * @method dealloc

pyobjc-core/Modules/objc/OC_PythonDictionary.h

  *
  * Caller must own the GIL
  */
-+ depythonifyObject:(PyObject*)object;
++(OC_PythonDictionary*)depythonifyObject:(PyObject*)object;
 
 
 /*!
  *
  * The caller must own the GIL.
  */
-+ dictionaryWithPythonObject:(PyObject*)value;
++(OC_PythonDictionary*)dictionaryWithPythonObject:(PyObject*)value;
 
 /*!
  * @method initWithPythonObject:
  *
  *    The caller must own the GIL.
  */
-- initWithPythonObject:(PyObject*)value;
+-(OC_PythonDictionary*)initWithPythonObject:(PyObject*)value;
 
 /*!
  * @method dealloc
 
 /* These two are only present to *disable* coding, not implement it */
 - (void)encodeWithCoder:(NSCoder*)coder;
-- initWithCoder:(NSCoder*)coder;
+-(id)initWithCoder:(NSCoder*)coder;
 
 @end /* interface OC_PythonDictionary */

pyobjc-core/Modules/objc/OC_PythonObject.h

 }
 
 + (int)wrapPyObject:(PyObject *)argument toId:(id *)datum;
-+ objectWithPythonObject:(PyObject *) obj;
-+ depythonifyTable;
-+ pythonifyStructTable;
++ (id <NSObject>)objectWithPythonObject:(PyObject *) obj;
++ (id)depythonifyTable;
++ (id)pythonifyStructTable;
 + (PyObject *)__pythonifyStruct:(PyObject *) obj withType:(const char *) type length:(Py_ssize_t) length;
-+ objectWithCoercedPyObject:(PyObject *) obj;
-- initWithPyObject:(PyObject *) obj;
++ (id <NSObject>)objectWithCoercedPyObject:(PyObject *) obj;
+- (id)initWithPyObject:(PyObject *) obj;
 
 /*!
  * @method pyObject
 /* Key-Value Coding support */
 + (BOOL)useStoredAccessor;
 + (BOOL)accessInstanceVariablesDirectly;
-- valueForKey:(NSString*) key;
+- (id)valueForKey:(NSString*) key;
 - (NSDictionary*) valuesForKeys: (NSArray*)keys;
-- valueForKeyPath: (NSString*) keyPath;
-- storedValueForKey: (NSString*) key;
+- (id)valueForKeyPath: (NSString*) keyPath;
+- (id)storedValueForKey: (NSString*) key;
 - (void)takeValue: value forKey: (NSString*) key;
 - (void)setValue: value forKey: (NSString*) key;
 - (void)setValue: value forKeyPath: (NSString*) key;
 
 /* These two are only present to *disable* coding, not implement it */
 - (void)encodeWithCoder:(NSCoder*)coder;
-- initWithCoder:(NSCoder*)coder;
-+classFallbacksForKeyedArchiver;
+- (id)initWithCoder:(NSCoder*)coder;
++ (id)classFallbacksForKeyedArchiver;
 -(NSObject*)replacementObjectForArchiver:(NSObject*)archiver;
 -(NSObject*)replacementObjectForKeyedArchiver:(NSObject*)archiver;
 -(NSObject*)replacementObjectForCoder:(NSObject*)archiver;

pyobjc-core/Modules/objc/OC_PythonObject.m

 	return r;
 }
 
-+ objectWithPythonObject:(PyObject *) obj
++(id <NSObject>)objectWithPythonObject:(PyObject *) obj
 {
 	id instance;
 	if (likely(PyObjCObject_Check(obj))) {
 	return instance;
 }
 
-+ objectWithCoercedPyObject:(PyObject *)obj
++(id <NSObject>)objectWithCoercedPyObject:(PyObject *)obj
 {
 	id instance;
 	PyObjC_BEGIN_WITH_GIL
 	return instance;
 }
 
-+ depythonifyTable
++(id)depythonifyTable
 {
 	PyObjC_BEGIN_WITH_GIL
 		if (OC_PythonObject_DepythonifyTable == NULL) {
 	PyObjC_END_WITH_GIL
 }
 
-+ pythonifyStructTable
++(id)pythonifyStructTable
 {
 	PyObjC_BEGIN_WITH_GIL
 		if (OC_PythonObject_PythonifyStructTable == NULL) {
 	PyObjC_END_WITH_GIL
 }
 
-+ (PyObject *)__pythonifyStruct:(PyObject*)obj withType:(const char *)type length:(Py_ssize_t)length
++(PyObject *)__pythonifyStruct:(PyObject*)obj withType:(const char *)type length:(Py_ssize_t)length
 {
 	if (OC_PythonObject_PythonifyStructTable == NULL) {
 		Py_INCREF(obj);
 	return PyObject_CallFunctionObjArgs(convert, obj, NULL);
 }
 
-- initWithPyObject:(PyObject *) obj
+-(id)initWithPyObject:(PyObject *) obj
 {
 	PyObjC_BEGIN_WITH_GIL
 		if (pyObject) {
         
 
 
-- (void)dealloc
+-(void)dealloc
 {
 	PyObjC_BEGIN_WITH_GIL
 		PyObjC_UnregisterObjCProxy(pyObject, self);
 	[super dealloc];
 }
 
--copyWithZone:(NSZone*)zone
+-(id)copyWithZone:(NSZone*)zone
 {
 	(void)zone;
 	NSObject* result = nil;
 	return result;
 }
 
--copy
+-(id)copy
 {
 	return [self copyWithZone:NULL];
 }
 
 /* Undocumented method used by NSLog, this seems to work. */
-- (NSString*) _copyDescription
+-(NSString*) _copyDescription
 {
 	return [[self description] copy];
 }
 
-- (NSString*) description
+-(NSString*) description
 {
 	PyObject *repr;
 
 	return @"a python object";
 }
   
-- (void) doesNotRecognizeSelector:(SEL) aSelector
+-(void)doesNotRecognizeSelector:(SEL) aSelector
 {
 	[NSException raise:NSInvalidArgumentException
 				format:@"%@ does not recognize -%s",
 }
 
 
-- (BOOL) respondsToSelector:(SEL) aSelector
+-(BOOL)respondsToSelector:(SEL) aSelector
 {
 	PyObject *m;
 	Method* methods;
 	return nil;
 }
 
-- (NSMethodSignature *) methodSignatureForSelector:(SEL) sel
+-(NSMethodSignature *) methodSignatureForSelector:(SEL) sel
 {
 	/* We can't call our superclass implementation, NSProxy just raises
 	 * an exception.
 	return [NSMethodSignature signatureWithObjCTypes:encoding];
 }
 
-- (BOOL) _forwardNative:(NSInvocation*) invocation
+-(BOOL)_forwardNative:(NSInvocation*) invocation
 {
 	/* XXX: This should use libffi to call call native methods of this
 	 *      class. The implementation below works good enough for
 	return NO;
 }
 
-- (void) forwardInvocation:(NSInvocation *) invocation
+-(void)forwardInvocation:(NSInvocation *) invocation
 {
 	/* XXX: Needs cleanup */
 	NSMethodSignature* msign = [invocation methodSignature];
 }
 
 
-- (PyObject *)  pyObject
+-(PyObject *)pyObject
 {
 	return pyObject;
 }
 
-- (PyObject *)  __pyobjc_PythonObject__
+-(PyObject *)__pyobjc_PythonObject__
 {
 	PyObjC_BEGIN_WITH_GIL
-#if 1
 		if (pyObject == NULL) {
-#if 1
 			PyObject* r = PyObjCObject_New(self, PyObjCObject_kDEFAULT, YES);
 			PyObjC_GIL_RETURN(r);
-#else
-			Py_INCREF(Py_None);
-			PyObjC_GIL_RETURN(Py_None);
-#endif
-		} else 
-#endif
-		{
+		} else {
 			Py_XINCREF(pyObject);
 			PyObjC_GIL_RETURN(pyObject);
 		}
 /*
  *  Call PyObjCTools.KeyValueCoding.getKey to get the value for a key
  */
-- valueForKey:(NSString*) key
+-(id)valueForKey:(NSString*) key
 {
 static  PyObject* getKeyFunc = NULL;
 
 	return res;
 }
 
-- storedValueForKey: (NSString*) key
+-(id)storedValueForKey: (NSString*) key
 {
 	return [self valueForKey: key];
 }
 /* Calls PyObjCTools.KeyValueCoding.setKey to set the key */
 
 /* This is the 10.2 flavour of this method, deprecated in 10.3 */
-- (void)takeValue: value forKey: (NSString*) key
+-(void)takeValue: value forKey: (NSString*) key
 {
 	[self setValue: value forKey: key];
 }
 
-- (void)setValue: value forKey: (NSString*) key
+-(void)setValue: value forKey: (NSString*) key
 {
 static  PyObject* setKeyFunc = NULL;
 
 	PyObjC_END_WITH_GIL
 }
 
-- (void)takeStoredValue: value forKey: (NSString*) key
+-(void)takeStoredValue: value forKey: (NSString*) key
 {
 	[self takeValue: value forKey: key];
 }
 
-- (NSDictionary*) valuesForKeys: (NSArray*)keys
+-(NSDictionary*)valuesForKeys: (NSArray*)keys
 {
 	NSMutableDictionary* result;
 	NSEnumerator* enumerator;
 	return result;
 }
 
-- valueForKeyPath: (NSString*) keyPath
+-(id)valueForKeyPath: (NSString*) keyPath
 {
 	NSArray* elems = [keyPath componentsSeparatedByString:@"."];
 	NSEnumerator* enumerator = [elems objectEnumerator];
 }
 
 /* takeValue:forKeyPath: was deprecated in 10.3, and is the right way on 10.2 */
-- (void)takeValue: value forKeyPath: (NSString*)keyPath
+-(void)takeValue: value forKeyPath: (NSString*)keyPath
 {
 	[self setValue: value forKeyPath: keyPath];
 }
 	
-- (void)setValue: value forKeyPath: (NSString*) keyPath
+-(void)setValue: value forKeyPath: (NSString*) keyPath
 {
 	NSArray* elems = [keyPath componentsSeparatedByString:@"."];
 	id target;
 	[target takeValue: value forKey: [elems objectAtIndex: len-1]];
 }
 
-- (void)takeValuesFromDictionary: (NSDictionary*) aDictionary
+-(void)takeValuesFromDictionary: (NSDictionary*) aDictionary
 {
 	[self setValuesForKeysWithDictionary: aDictionary];
 }
 
-- (void)setValuesForKeysWithDictionary: (NSDictionary*) aDictionary
+-(void)setValuesForKeysWithDictionary: (NSDictionary*) aDictionary
 {
 	NSEnumerator* enumerator = [aDictionary keyEnumerator];
 	id aKey;
 	}
 }
 
-- (void)unableToSetNilForKey: (NSString*) key
+-(void)unableToSetNilForKey: (NSString*) key
 {
 	[NSException 
 		raise: NSUnknownKeyException 
 		format: @"cannot set Nil for key: %@", key];
 }
 
-- (void)handleQueryWithUnboundKey: (NSString*) key
+-(void)handleQueryWithUnboundKey: (NSString*) key
 {
 	[self valueForUndefinedKey: key];
 }
 
-- (void)valueForUndefinedKey: (NSString*)key
+-(void)valueForUndefinedKey: (NSString*)key
 {
 	[NSException 
 		raise: NSUnknownKeyException
 		format: @"query for unknown key: %@", key];
 }
 
-- (void)handleTakeValue: value forUnboundKey: (NSString*) key
+-(void)handleTakeValue: value forUnboundKey: (NSString*) key
 {
 	[self setValue: value forUndefinedKey: key];
 }
 
-- (void)setValue: value forUndefinedKey: (NSString*) key
+-(void)setValue: value forUndefinedKey: (NSString*) key
 {
 	[NSException 
 		raise: NSUnknownKeyException 
 }
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
-- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
+-(void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
 {
 	NSLog(@"*** Ignoring *** %@ for '%@' (of %@ with %#lx in %p).\n", NSStringFromSelector(_cmd), keyPath, observer, (long)options, context);
 	return;
 }
-- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath
+-(void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath
 {
 	NSLog(@"*** Ignoring *** %@ for '%@' (of %@).", NSStringFromSelector(_cmd), keyPath, observer);
 }
 #endif
 
 /* NSObject protocol */
-- (NSUInteger)hash
+-(NSUInteger)hash
 {
     PyObjC_BEGIN_WITH_GIL
         int rval;
     PyObjC_END_WITH_GIL
 }
 
-- (BOOL)isEqual:(id)anObject
+-(BOOL)isEqual:(id)anObject
 {
     if (anObject == nil) {
         return NO;
 }
 
 /* NSObject methods */
-- (NSComparisonResult)compare:(id)other
+-(NSComparisonResult)compare:(id)other
 {
     if (other == nil) {
         [NSException raise: NSInvalidArgumentException
 /*
  * Support of the NSCoding protocol
  */
-- (void)encodeWithCoder:(NSCoder*)coder
+-(void)encodeWithCoder:(NSCoder*)coder
 {
 	PyObjC_encodeWithCoder(pyObject, coder);
 }
 	pyObject = value;
 }
 
-- initWithCoder:(NSCoder*)coder
+-(id)initWithCoder:(NSCoder*)coder
 {
 	pyObject = NULL;
 
  * Luckily that's kind of easy, we know the entiry class hierarcy and also
  * know there are no subclasses.
  */
-- (BOOL)isKindOfClass:(Class)aClass
+-(BOOL)isKindOfClass:(Class)aClass
 {
 	if (aClass == [NSProxy class] || aClass == [OC_PythonObject class]) {
 		return YES;
 }
 
 
-+classFallbacksForKeyedArchiver
++(id)classFallbacksForKeyedArchiver
 {
 	return nil;
 }

pyobjc-core/Modules/objc/OC_PythonUnicode.h

 @interface OC_PythonUnicode : NSString
 {
 	PyObject* value;
-#ifndef PyObjC_UNICODE_FAST_PATH
 	id realObject;
-#endif /* !PyObjC_UNICODE_FAST_PATH */
+
+	/* Cache IMPs for proxied methods, for slightly better efficiency */
+	NSUInteger (*imp_length)(id, SEL);
+	unichar (*imp_charAtIndex)(id, SEL, NSUInteger);
+	void (*imp_getCharacters)(id, SEL, unichar*, NSRange);
 }
 
 /*!
  *
  * Caller must own the GIL.
  */
-+ unicodeWithPythonObject:(PyObject*)value;
++(id)unicodeWithPythonObject:(PyObject*)value;
 
 /*!
  * @method initWithPythonObject:
  *
  * Caller must own the GIL.
  */
-- initWithPythonObject:(PyObject*)value;
+-(id)initWithPythonObject:(PyObject*)value;
 
 /*!
  * @method dealloc
  */
 -(PyObject*)__pyobjc_PythonObject__;
 
-#ifndef PyObjC_UNICODE_FAST_PATH
-/*!
- * @abstract Access the NSString* representing the unicode
- * @result Returns a backing NSString* object
- */
--(id)__realObject__;
-#endif /* !PyObjC_UNICODE_FAST_PATH */
-
 /*
  * Primitive NSString methods
  *

pyobjc-core/Modules/objc/OC_PythonUnicode.m

 	OC_PythonUnicode* res;
 
 	res = [[OC_PythonUnicode alloc] initWithPythonObject:v];
-	[res autorelease];
+//	[res autorelease];
 	return res;
 }
 
 		PyObjC_UnregisterObjCProxy(value, self);
 #ifndef PyObjC_UNICODE_FAST_PATH
 		[realObject release];
+#else
+		[realObject release];
 #endif /* !PyObjC_UNICODE_FAST_PATH */
 		Py_XDECREF(value);
 	PyObjC_END_WITH_GIL
 	[super dealloc];
 }
 
-#ifdef PyObjC_UNICODE_FAST_PATH
+/*
+ * XXX: The code below should work for PyObjC_UNICODE_FAST_PATH 
+ * but causes failures on 64-bit builds on OSX 10.7
+ *
 
 -(NSUInteger)length
 {
 
 -(unichar)characterAtIndex:(NSUInteger)anIndex
 {
-	Py_ssize_t offset;
 	if (anIndex > PY_SSIZE_T_MAX) {
 		[NSException raise:@"NSRangeException" format:@"Range or index out of bounds"];
 	}
 		[NSException raise:@"NSRangeException" format:@"Range or index out of bounds"];
 	}
 
-	offset = (Py_ssize_t)anIndex;
-	unichar ch = PyUnicode_AS_UNICODE(value)[offset];
-	return ch;
+	return (unichar)PyUnicode_AS_UNICODE(value)[anIndex];
 }
 
 -(void)getCharacters:(unichar *)buffer range:(NSRange)aRange
 {
-	Py_ssize_t offset;
-	size_t length;
-
 	if (aRange.location + aRange.length > (NSUInteger)PyUnicode_GET_SIZE(value)) {
 		[NSException raise:@"NSRangeException" format:@"Range or index out of bounds"];
 	}
 
-	offset = (Py_ssize_t)(aRange.location);
-	length = (size_t)aRange.length;
-
-	memcpy(buffer, 
-	       (PyUnicode_AS_UNICODE(value)) + offset,
-	       2 * length);
+	memmove(buffer, 
+	       (PyUnicode_AS_UNICODE(value)) + aRange.location,
+	       sizeof(unichar) * aRange.length);
 }
 
-#else /* !PyObjC_UNICODE_FAST_PATH */
+*/
+
+
+#if PY_VERSION_HEX >= 0x03030000
+
+-(id)__realObject__
+{
+	if (!realObject) {
+		switch (PyUnicode_KIND(value)) {
+		case PyUnicode_1BYTE_KIND:
+			if (PyUnicode_IS_ASCII(value)) {
+				realObject = [[NSString alloc]
+					initWithBytesNoCopy:PyUnicode_1BYTE_DATA(value)
+					       length:(NSUInteger)PyUnicode_GET_SIZE(value)
+					     encoding:NSASCIIStringEncoding
+					 freeWhenDone:NO];
+			} else {
+				realObject = [[NSString alloc]
+					initWithBytesNoCopy:PyUnicode_1BYTE_DATA(value)
+					       length:(NSUInteger)PyUnicode_GET_SIZE(value)
+					     encoding:NSISOLatin1StringEncoding
+					 freeWhenDone:NO];
+			
+			}
+			break;
+
+		case PyUnicode_2BYTE_KIND:
+			realObject = [[NSString alloc]
+				initWithCharactersNoCopy:PyUnicode_2BYTE_DATA(value)
+				       length:(NSUInteger)PyUnicode_GET_SIZE(value)
+				 freeWhenDone:NO];
+			break;
+
+		case PyUnicode_WCHAR_KIND:
+			/* wchar_t representation, treat same
+			 * as UCS4 strings
+			 */
+		case PyUnicode_4BYTE_KIND:
+			PyObjC_BEGIN_WITH_GIL
+				PyObject* utf8 = PyUnicode_AsUTF8String(value);
+				if (!utf8) {
+					NSLog(@"failed to encode unicode string to byte string");
+					PyErr_Clear();
+				} else {
+					realObject = [[NSString alloc]
+						initWithBytes:PyBytes_AS_STRING(utf8)
+						       length:(NSUInteger)PyBytes_GET_SIZE(utf8)
+						     encoding:NSUTF8StringEncoding];
+					Py_DECREF(utf8);
+				}
+			PyObjC_END_WITH_GIL
+		}
+	}
+	return realObject;
+}
+
+#elif defined(PyObjC_UNICODE_FAST_PATH)
+
+-(id)__realObject__
+{
+	if (!realObject) {
+		realObject = [[NSString alloc]
+			initWithCharactersNoCopy:PyUnicode_AS_UNICODE(value)
+			       length:(NSUInteger)PyUnicode_GET_SIZE(value)
+			 freeWhenDone:NO];
+	}
+	return realObject;
+}
+
+#else // !PyObjC_UNICODE_FAST_PATH */
+
+/* XXX: Add __realObject__ implementation tuned for Python 3.3 (choose right
+ *      NSString constructor based on unicode representation size
+ */
 
 -(id)__realObject__
 {
 	}
 	return realObject;
 }
-	
+#endif	
+
 -(NSUInteger)length
 {
-	return [((NSString *)[self __realObject__]) length];
+	if (!imp_length) {
+		[self __realObject__];
+		imp_length = (__typeof__(imp_length))([realObject methodForSelector:@selector(length)]);
+	}
+	if (!imp_length) abort();
+	if (!realObject) abort();
+	return imp_length(realObject, @selector(length));
 }
 
 -(unichar)characterAtIndex:(NSUInteger)anIndex
 {
-
-	unichar ch = [((NSString *)[self __realObject__]) characterAtIndex:anIndex];
-	return ch;
+	if (!imp_charAtIndex) {
+		[self __realObject__];
+		imp_charAtIndex = (__typeof__(imp_charAtIndex))([realObject methodForSelector:@selector(characterAtIndex:)]);
+	}
+	if (!imp_charAtIndex) abort();
+	if (!realObject) abort();
+	return imp_charAtIndex(realObject, @selector(characterAtIndex:), anIndex);
 }
 
 -(void)getCharacters:(unichar *)buffer range:(NSRange)aRange
 {
-	[((NSString *)[self __realObject__]) getCharacters:buffer range:aRange];
+	if (!imp_getCharacters) {
+		[self __realObject__];
+		imp_getCharacters = (__typeof__(imp_getCharacters))([realObject methodForSelector:@selector(getCharacters:range:)]);
+	}
+	if (!imp_getCharacters) abort();
+	if (!realObject) abort();
+	imp_getCharacters(realObject, @selector(getCharacters:range:), buffer, aRange);
 }
 
-#endif /* PyObjC_UNICODE_FAST_PATH */
-
 /*
  * NSCoding support 
  *
 	}
 }
 
-#if 1
-
-
 -(NSObject*)replacementObjectForArchiver:(NSArchiver*)archiver 
 {
 	(void)(archiver);
 	return [NSArray arrayWithObject:@"NSString"];
 }
 
-#endif
 
 @end /* implementation OC_PythonUnicode */

pyobjc-core/Modules/objc/libffi_support.m

 					return -1;
 				}
 
-				if (PyUnicode_AsWideChar(v, (wchar_t*)byref[curarg], sz)<0) {
+				if (PyUnicode_AsWideChar(UNICODE_CAST(v), (wchar_t*)byref[curarg], sz)<0) {
 					Py_DECREF(encoded);
 					return -1;
 				}

pyobjc-core/Modules/objc/pyobjc-api.h

 	PyObject* (*c_array_to_py)(const char*, void*, Py_ssize_t);
 
 	/* PyObjC_RegisterStructType */
-	PyObject* (*register_struct)(const char*, const char*, const char*, initproc, Py_ssize_t, const char**);
+	PyObject* (*register_struct)(const char*, const char*, const char*, initproc, Py_ssize_t, const char**, Py_ssize_t);
 
 	/* PyObjCIMP_Type */
 	PyTypeObject* imp_type;

pyobjc-core/Modules/objc/pyobjc-compat.h

 #define Py_ARG_BYTES "z"
 #endif
 
+/* Cast a PyObject* to the type expected by the 2.x C API. 
+ * This is a macro because the cast is not necessary for the 3.x C API)
+ */
+#define UNICODE_CAST(item)  ((PyUnicodeObject*)(item))
+#define SLICE_CAST(item)	   ((PySliceObject*)(item))
+
 #else
 
 #ifndef Py_ARG_BYTES
 #define Py_ARG_BYTES "y"
 #endif
 
+#define UNICODE_CAST(item)	(item)
+#define SLICE_CAST(item)	(item)
+
 #endif
 
 #if __LP64__

pyobjc-core/Modules/objc/pyobjc.h

  * unicode strings due to unexplained
  * test failures.
  */
+#if 0
 #ifdef PyObjC_UNICODE_FAST_PATH
 #undef PyObjC_UNICODE_FAST_PATH
 #endif
+#endif
 
 #include "objc-runtime-compat.h"
 #include "proxy-registry.h"

pyobjc-core/Modules/objc/struct-wrapper.m

 		PyObject* result;
 		PyObject* it;
 
-		if (PySlice_GetIndicesEx(item, 
+		if (PySlice_GetIndicesEx(SLICE_CAST(item), 
 				struct_sq_length(self),
 				&start, &stop, &step, &slicelength) < 0) {
 			return NULL;
 	} else if (PySlice_Check(item)) {
 		Py_ssize_t start, stop, step, slicelength;
 
-		if (PySlice_GetIndicesEx(item, 
+		if (PySlice_GetIndicesEx(SLICE_CAST(item), 
 				struct_sq_length(self), &start, &stop,
 				&step, &slicelength) < 0) {
 			return -1;

pyobjc-core/Modules/objc/super-call.m

 {
 	[NSException raise:NSInvalidArgumentException
 		format:@"Implementing %s from Python is not supported for %@",
-			*(id*)args[0], sel_getName(*(SEL*)args[1])];
+			sel_getName(*(SEL*)args[1]),
+			*(id*)args[0]]; 
 }
 
 PyObject* 

pyobjc-core/Modules/objc/test/copying.m

 	NSObject<NSCopying>* tmp;
 	NSObject* retval;
 
-	tmp = (NSObject*)[[aClass alloc] init];
+	tmp = (NSObject<NSCopying>*)[[aClass alloc] init];
 	[tmp modify];
 
 	retval = [tmp copyWithZone:nil];

pyobjc-core/Modules/objc/test/exceptions.m

 
 static NSString* addSomeUnicode(NSString* input)
 {
-	return [NSString stringWithFormat:@"%@%C%C", input, 0x1234, 0x2049];
+	return [NSString stringWithFormat:@"%@%C%C", input, (short)0x1234, (short)0x2049];
 }
 
 @interface PyObjCTestExceptions : NSObject

pyobjc-core/Modules/objc/test/fsref.m

 	rc = FSPathMakeRef((UInt8*)[path UTF8String],
 		&fsref, &isDirectory);
 	if (rc != 0) {
-		[NSException raise:@"failure" format:@"status: %d", rc];
+		[NSException raise:@"failure" format:@"status: %ld", (long)rc];
 	}
 
 	return fsref;
 
 	rc = FSRefMakePath(fsref, buffer, sizeof(buffer));
 	if (rc != 0) {
-		[NSException raise:@"failure" format:@"status: %d", rc];
+		[NSException raise:@"failure" format:@"status: %ld", (long)rc];
 	}
 
 	return [NSString stringWithUTF8String: (char*)buffer];
 	rc = FSPathMakeRef((UInt8*)[path UTF8String],
 		fsref, &isDirectory);
 	if (rc != 0) {
-		[NSException raise:@"failure" format:@"status: %d", rc];
+		[NSException raise:@"failure" format:@"status: %ld", (long)rc];
 	}
 }
 

pyobjc-core/libffi-src/x86/x86-ffi_darwin.c

 /* ffi_prep_args is called by the assembly routine once stack space
  has been allocated for the function's arguments */
 
+void ffi_prep_args(char *stack, extended_cif *ecif);
+
 void ffi_prep_args(char *stack, extended_cif *ecif)
 {
     register unsigned int i;

pyobjc-core/setup.py

 #    "-Wno-long-long",
     "-W",
 
-
+    "-fcatch-undefined-behavior",
+    "-Wno-missing-method-return-type", # XXX
     "-Wno-import",
     "-DPyObjC_BUILD_RELEASE=%02d%02d"%(tuple(map(int, get_os_level().split('.')))),
     #"-Warray-bounds", # XXX: Needed to avoid False positives for PyTuple access macros

pyobjc-framework-Cocoa/PyObjCTest/test_cfstring.py

         trim_chars = b'a'.decode('ascii')
 
         # XXX: CoreFoundation API regularly fails when second argument is a non-Apple NSString
-        trim_chars = CFStringCreateWithCString(None, b"a", kCFStringEncodingASCII)
+        #trim_chars = CFStringCreateWithCString(None, b"a", kCFStringEncodingASCII)
+        print >>sys.stderr, ("@@@@@@@ BEFORE TRIM @@@@@@")
         CFStringTrim(s, trim_chars)
+        print >>sys.stderr, ("@@@@@@@ AFTER TRIM @@@@@@")
         self.assertEqual(s, b"Hello".decode('ascii'))
 
         # XXX: CoreFoundation API regularly fails when second argument is a non-Apple NSString