PerlObjCBridge fun fact

pemungkah on 2005-02-23T22:50:08

From James Duncan's blog:

As I wrote before, PerlObjCBridge is available in Mac OS X's system perl to provide a calling bridge between Perl, and Objective-C. It ships also with Foundation, which is Apple's fundamental elements of Cocoa library.

However, having access to Foundation doesn't buy you very much, but luckily everything you need to be able to load other frameworks is present.

The trick is using NSBundle to load the frameworks at run time.
  my $frameworkPath = NSString->stringWithCString('/path/to/a/framework');
  my $framework = NSBundle->alloc->init->initWithPath_($frameworkPath);
  $framework->load();
Once this has been done the classes in the framework are available to you, however, you need to perform one last bit of magic to really use them. You need to declare the class in Perl and have it inherit from PerlObjCBridge to have messages passed along.
  package NSWhatever;

use base qw( PerlObjCBridge );
And hey presto! You should have access to the class you want.


I *think* this means I ought to be able to load the necessary Cocoa classes and CoreAudio into Perl, thereby getting a pretty GUI, the synthesis code, and being able to use Sean's chime code without having to change it.

Copied here so I don't have to look at the comment spam, which makes my eyes bleed.


Thanks!

pudge on 2005-03-02T17:48:04

I was working on Mac::Growl, a perl binding for Growl. It originally worked with Foundation, and I made it so that if Foundation is unavailable, it would use Mac::Glue or AppleScript. Then we wanted image support, which I added to the Mac::Glue and AppleScript code, but could not add to the Foundation code, since NSImage and NSWorkspace are in AppKit. Anyway, here's the code I added:
        my $path = NSString->stringWithCString_('/System/Library/Frameworks/AppKit.framework');
        $appkit = NSBundle->alloc->init->initWithPath_($path);
        $appkit->load if $appkit;
        if ($appkit->isLoaded) {
            no strict 'refs';
            for my $class (qw(NSWorkspace NSImage)) {
                @{$class . '::ISA'} = 'PerlObjCBridge';
            }
        } else {
            undef $appkit;
        }
Then later:
    if ($appkit && defined $iconOfApp) {
        my $path = NSWorkspace->sharedWorkspace->fullPathForApplication_(
            NSString->stringWithCString_($iconOfApp)
        );
        if ($path) {
            my $icon = NSWorkspace->sharedWorkspace->iconForFile_($path);
            if ($icon && $icon->isValid) {
                $regDict->setObject_forKey_($icon->TIFFRepresentation, GROWL_APP_ICON);
            }
        }
    }
and:
    if ($appkit && defined $image && -e $image) {
        my $path = NSString->stringWithCString_($image);
        if ($path) {
            my $icon = NSImage->alloc->initWithContentsOfFile_($path);
            if ($icon && $icon->isValid) {
                $noteDict->setObject_forKey_($icon->TIFFRepresentation, GROWL_NOTIFICATION_ICON);
            }
        }
    }
Took me awhile to get it all working, but it is working now. Again, thanks!

Re:Thanks!

pemungkah on 2005-03-02T23:31:25

Glad I could help. My Cocoa-fu is still almost nonexistent, but that was such a good hack I had to put it somewhere I wouldn't lose it.