Tuesday, August 5, 2008

PyObjC calls Objective-C names

I read in the Apple docs about PyObjcC that:
your projects can be a mix of Objective-C, C, and C++ code
so I worked up an example. It is simpler than my previous one which depends on having a bundle already compiled.

The project is a Cocoa-Python application. The AppDelegate instantiates the class and calls the code we are going to write in Objective-C:

    def applicationDidFinishLaunching_(self, sender):
NSLog("Application did finish launching.")
e = example.alloc().init()

NSLog("%s" % example.description())
s = e.fetchResource()
print self.description(), s
print

c = e.fetchObject()
print self.description()
print c.description()

n = e.compute_(10)
print n

The .h and .c files for the Objective C class that we've added to this project are here (some lines in this post are too long for the code window, copy and paste to a text file if you need to see it all). We've added a text file called "stuff.txt" to the project:

#import < Cocoa/Cocoa.h>

@interface example : NSObject {

NSColorList *CL;
NSColor *c;
int n;
}
- (NSString *)fetchResource;
- (NSColor *)fetchObject;
- (int)compute:(int) anInt;

@end

#import "example.h"

@implementation example

- (NSString *)fetchResource
{
NSLog(@"%@", [self className]);
NSString *path = [[NSBundle mainBundle] pathForResource:@"stuff" ofType:@"txt"];
NSLog(@"%@", [path description]);

const char * cstring = [path cStringUsingEncoding:NSASCIIStringEncoding];
printf("path %s\n", cstring);
NSString *s = [NSString stringWithCString:cstring];
return s;
}

- (NSColor *)fetchObject
{
CL = [NSColorList colorListNamed:@"Crayons"];
c = [CL colorWithKey:@"Salmon"];
NSLog(@"%@", [c description]);
//[c retain];
return c;
}

- (int)compute:(int) anInt
{
n = anInt * 2;
return n;
}

@end

We can't import the example class from Python, we have to do this in "main.m." (There is an extra space in the import statement before I escape the <. I'm not that handy with html):

#import < Python/Python.h>
#import < Cocoa/Cocoa.h>
#import < example.h>

And this is what it prints to the Console:

[Session started at 2008-08-05 19:07:39 -0400.]
2008-08-05 19:07:40.872 PyBundle[5274:10b] Application did finish launching.
2008-08-05 19:07:40.874 PyBundle[5274:10b] example
2008-08-05 19:07:40.874 PyBundle[5274:10b] example
2008-08-05 19:07:40.875 PyBundle[5274:10b] /Users/telliott_admin/Desktop/PyBundle/build/Release/PyBundle.app/Contents/Resources/stuff.txt
path /Users/telliott_admin/Desktop/PyBundle/build/Release/PyBundle.app/Contents/Resources/stuff.txt
/Users/telliott_admin/Desktop/PyBundle/build/Release/PyBundle.app/Contents/Resources/stuff.txt

2008-08-05 19:07:40.941 PyBundle[5274:10b] NSCalibratedRGBColorSpace 1 0.4 0.4 1

NSCalibratedRGBColorSpace 1 0.4 0.4 1
20