Hacking Mac OSX Cocoa API from Perl

50
Hacking Mac OS X Cocoa API from Perl Daisuke Murase (typester) YAPC::Asia Tokyo 2011

Transcript of Hacking Mac OSX Cocoa API from Perl

Page 1: Hacking Mac OSX Cocoa API from Perl

Hacking Mac OS X Cocoa API from Perl

Daisuke Murase (typester)YAPC::Asia Tokyo 2011

Page 2: Hacking Mac OSX Cocoa API from Perl

About me

• Daisuke Murase

• KAYAC Inc. (2004 - present)

• This year’s work:

Page 3: Hacking Mac OSX Cocoa API from Perl

About me

• Daisuke Murase

• KAYAC Inc. (2004 - present)

• This year’s work:

• Reengo(Facebook integrated VoIP application for iOS)

Page 4: Hacking Mac OSX Cocoa API from Perl

About me

• Daisuke Murase

• KAYAC Inc. (2004 - present)

• This year’s work:

• Reengo(Facebook integrated VoIP application for iOS)

• VQ Checker (Voice Quotient analyzer for PC and iOS)

Page 5: Hacking Mac OSX Cocoa API from Perl

About me

• Daisuke Murase

• KAYAC Inc. (2004 - present)

• This year’s work:

• Reengo(Facebook integrated VoIP application for iOS)

• VQ Checker (Voice Quotient analyzer for PC and iOS)

• One more thing...(Will be released before this xmas!)

Page 6: Hacking Mac OSX Cocoa API from Perl

About me

• a.k.a typester

Page 7: Hacking Mac OSX Cocoa API from Perl

About me

• a.k.a typester• http://search.cpan.org/~TYPESTER/• http://github.com/typester• http://facebook.com/typester• http://twitter.com/typester

Page 8: Hacking Mac OSX Cocoa API from Perl

♥ Mazda Roadster (known as MX-5 in other countries)

Page 9: Hacking Mac OSX Cocoa API from Perl

Agenda

• A little knowledge about Objective-C• How to use Objective-C from Perl• A little knowledge about XS• Some tips about XS and Objective-C• Introducing Cocoa:: modules I’ve created

Page 10: Hacking Mac OSX Cocoa API from Perl

Objective-C

Page 11: Hacking Mac OSX Cocoa API from Perl

Objective-C

• Created for NextStep.• It’s currently used as primary programming language for Mac OS X.

• Implemented based C.All C syntax and features can be used in Objective-C file.

Page 12: Hacking Mac OSX Cocoa API from Perl

Objective-C

• #import <Foundation/Foundation.h>

int main(int argc, char** argv) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

// Objective-C code here NSLog(@”Hello World!”);

[pool drain]; return 0;}

Page 13: Hacking Mac OSX Cocoa API from Perl

Objective-C

• gcc -framework Foundation foo.m

Page 14: Hacking Mac OSX Cocoa API from Perl

Objective-C

• gcc -framework Foundation foo.m• (like gcc -lFoundation foo.c)

Page 15: Hacking Mac OSX Cocoa API from Perl

Objective-C

• gcc -framework Foundation foo.m• (like gcc -lFoundation foo.c)• ./a.out

Page 16: Hacking Mac OSX Cocoa API from Perl

XS

• Foo.xs file is not use directly for C compiler

• Foo.xs will convert Foo.c by xsubpp• You can write Foo.c directly if you want.

Page 17: Hacking Mac OSX Cocoa API from Perl

Foo.c

• #include "EXTERN.h"#include "perl.h"#include "XSUB.h"#include "ppport.h"

XS(func) { dXSARGS;

// code here

XSRETURN(0);}

XS(boot_Foo) { newXS("Foo::xs_function", func, __FILE__);}

Page 18: Hacking Mac OSX Cocoa API from Perl

package Foo

• package Foo;use strict;use XSLoader;

XSLoader::load __PACKAGE__, $VERSION;

1;

Page 19: Hacking Mac OSX Cocoa API from Perl

Run it

• use Foo;

Foo::xs_function();

Page 20: Hacking Mac OSX Cocoa API from Perl

Makefile.PL for Foo.c

• use inc::Module::Install;

# some basic descriptions here

use_ppport '3.19';

WriteAll;

• (Module::Install::XSUtil)++

• See also Data::MessagePack, Data::AMF::XS, that is using this pseudo-XS technique.

Page 21: Hacking Mac OSX Cocoa API from Perl

Makefile.PL for Foo.m

Page 22: Hacking Mac OSX Cocoa API from Perl

Makefile.PL for Foo.m

• use inc::Module::Install;

# some basic descriptions hereuse_ppport '3.19';cc_append_to_libs '-lobjc';

makemaker_args->{dynamic_lib} = { OTHERLDFLAGS => '-framework Foundation',};

{ # http://www.mail-archive.com/[email protected]/msg02823.html # Add some required machinery to support .m files package MY; sub c_o { my $inherited = shift->SUPER::c_o(@_); $inherited .= <<'EOMESS';.m$(OBJ_EXT): $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.m

EOMESS $inherited; }

sub xs_c { my $inherited = shift->SUPER::xs_c(@_); $inherited .= <<'EOMESS';.xs.m: $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(XSUBPP_EXTRA_ARGS) $*.xs > $*.xsm && $(MV) $*.xsm $*.m

EOMESS $inherited; }

sub init_dirscan { my $self = shift; $self->SUPER::init_dirscan; foreach my $name ($self->lsdir($self->curdir)) {

Page 23: Hacking Mac OSX Cocoa API from Perl

Makefile.PL for Foo.m

• Sorry :)

Page 25: Hacking Mac OSX Cocoa API from Perl

That’s it

• Objective-C involve all C functions and features.

• Just rename Foo.c to Foo.m, it completely works by this Makefile.PL

• And of cause, you can use Objective-C specific syntax in this file!

Page 26: Hacking Mac OSX Cocoa API from Perl

Hello.m• #include "EXTERN.h"

#include "perl.h"#include "XSUB.h"#include "ppport.h"

// undefine Move macro, this is conflict to Mac OS X QuickDraw API.#undef Move

#import <Foundation/Foundation.h>

XS(hello) { dXSARGS;

NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSLog(@"Hello!"); [pool drain];

XSRETURN(0);}

XS(boot_Hello) { newXS("Hello::hello", hello, __FILE__);}

Page 27: Hacking Mac OSX Cocoa API from Perl

Copies and pastes for XS

• #include "EXTERN.h"#include "perl.h"#include "XSUB.h"#include "ppport.h"

Page 28: Hacking Mac OSX Cocoa API from Perl

Copies and pastes for XS

• #undef Move

Page 29: Hacking Mac OSX Cocoa API from Perl

Copies and pastes for XS

• XS(function) { dXSARGS; // code here XSRETURN(0);}

Page 30: Hacking Mac OSX Cocoa API from Perl

Copies and pastes for XS

• XS(function) { dXSARGS; // code here ST(0) = some_sv; XSRETURN(1);}

Page 31: Hacking Mac OSX Cocoa API from Perl

Copies and pastes for XS

• XS(function) { dXSARGS; // code here ST(0) = some_sv; ST(1) = some_sv2; XSRETURN(2);}

Page 32: Hacking Mac OSX Cocoa API from Perl

Copies and pastes for XS

• XS(function) { dXSARGS;

SV* sv_args1 = ST(0); SV* sv_args2 = ST(1); // code here

ST(0) = some_sv; ST(1) = some_sv2; XSRETURN(2);}

Page 33: Hacking Mac OSX Cocoa API from Perl

Copies and pastes for XS

• XS(function) { dXSARGS;

if (items < 2) { Perl_croak(aTHX_ "Usage: function($args1, $args2)"); }

SV* sv_args1 = ST(0); SV* sv_args2 = ST(1);

// code here ST(0) = some_sv; ST(1) = some_sv2; XSRETURN(2);}

Page 34: Hacking Mac OSX Cocoa API from Perl

for Objective-C and Perl

• Perl string to NSString

STRLEN len; char* c = SvPV(sv, len); NSString* str = [NSString stringWithUTF8String:c];

• NSString to Perl string

SV* sv = sv_2mortal(newSV(0)); sv_setpv(sv, [str UTF8String]);

Page 35: Hacking Mac OSX Cocoa API from Perl

for Objective-C and Perl

• Perl number to NSNumber

NSNumber* n;if (SvNOKp(sv)) { n = [NSNumber numberWithDouble:(double)SvNVX(sv))];}else if (SvIOK_UV(sv)) { n = [NSNumber numberWithDouble:(double)SvUV(sv))];}else if (SvIOKp(sv)) { n = [NSNumber numberWithDouble:(double)SvIV(sv))];}

• NSNumber to Perl number

SV* sv = sv_2mortal(newSVnv([n doubleValue]));

Page 36: Hacking Mac OSX Cocoa API from Perl

for Objective-C and Perl

• Snip.., described in my blog later• Perl array to NSArray• NSArray to Perl array• Perl hash to NSDictionary• NSDictionary to Perl hash

Page 37: Hacking Mac OSX Cocoa API from Perl

Don’t forget

• enable NSAutoreleasePool scope around your NS* objects

• otherwise the code will crash.

Page 38: Hacking Mac OSX Cocoa API from Perl

Your friends

• perldoc perlguts• perldoc perlapi• xcode documentation

Page 39: Hacking Mac OSX Cocoa API from Perl

Cocoa:: modules

Page 40: Hacking Mac OSX Cocoa API from Perl

Cocoa:: modules

• Cocoa::EventLoop• Cocoa::Growl• AnyEvent::Impl::Cocoa

Page 41: Hacking Mac OSX Cocoa API from Perl

Cocoa::EventLoop

• provides perl interface for Cocoa's event loop, NSRunLoop.

• also provides timers, I/O watchers acts with that event loop.

• You can handle event callbacks correctly by using this module.

Page 42: Hacking Mac OSX Cocoa API from Perl

Cocoa::Growl

• Perl interface for Growl.framework• Support click event with Cocoa::EventLoop

Page 43: Hacking Mac OSX Cocoa API from Perl

Cocoa::Growl

• use Cocoa::Growl ':all';

my $installed = growl_installed();my $running = growl_running();

Page 44: Hacking Mac OSX Cocoa API from Perl

Cocoa::Growl

• use Cocoa::Growl ':all';

# register applicationgrowl_register( app => 'My growl script', icon => '/path/to/icon.png', # or 'http://urlto/icon' notifications => [qw(Notification1 Notification2)],);

Page 45: Hacking Mac OSX Cocoa API from Perl

Cocoa::Growl

• use Cocoa::Growl ':all';

# show growl notificationgrowl_notify( name => 'Notification1', title => 'Hello!', description => 'Growl world!',);

Page 46: Hacking Mac OSX Cocoa API from Perl

Cocoa::Growl• use Cocoa::EventLoop;

use Cocoa::Growl ':all'; growl_register( name => 'test script', notifications => ['test notification'], ); my $wait = 1; growl_notify( name => 'test notification', title => 'Hello', description => 'Growl World!', on_click => sub { warn 'click'; $wait = 0; }, on_timeout => sub { warn 'timeout'; $want = 0; }, ); Cocoa::EventLoop->run_while(0.1) while unless $wait;

Page 47: Hacking Mac OSX Cocoa API from Perl

AnyEvent::Impl::Cocoa

• AnyEvent adaptor for Cocoa::EventLoop• you can use Cocoa based API in your AnyEvent application, or AnyEvent within Cocoa applications

Page 48: Hacking Mac OSX Cocoa API from Perl

AnyEvent::Impl::Cocoa

• Just do this:use AnyEvent;use Cocoa::EventLoop;

# then all anyevent based api use Cocoa::EventLoop!

Page 49: Hacking Mac OSX Cocoa API from Perl

AnyEvent::Impl::Cocoa

• use AnyEvent;use Cocoa::EventLoop;use Cocoa::Growl;

my $cv = AE::cv;growl_notify( name => 'test notification', title => 'Hello', description => 'Growl World!', on_click => sub { warn ‘click’; $cv->send; }, on_timeout => sub { warn ‘timeout’; $cv->send; },);$cv->recv;

Page 50: Hacking Mac OSX Cocoa API from Perl

Enjoy!