Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hacking Mac OS X Cocoa API from Perl

typester
November 18, 2011

Hacking Mac OS X Cocoa API from Perl

YAPC::Asia 2011 Tokyo

typester

November 18, 2011
Tweet

More Decks by typester

Other Decks in Programming

Transcript

  1. )BDLJOH.BD049$PDPB"1*
    GSPN1FSM
    %BJTVLF.VSBTF UZQFTUFS

    :"1$"TJB5PLZP

    View Slide

  2. "CPVUNF
    w %BJTVLF.VSBTF
    w ,":"$*OD QSFTFOU

    w 5IJTZFBS`TXPSL

    View Slide

  3. "CPVUNF
    w %BJTVLF.VSBTF
    w ,":"$*OD QSFTFOU

    w 5IJTZFBS`TXPSL
    w 3FFOHP
    'BDFCPPLJOUFHSBUFE7P*1BQQMJDBUJPOGPSJ04

    View Slide

  4. "CPVUNF
    w %BJTVLF.VSBTF
    w ,":"$*OD QSFTFOU

    w 5IJTZFBS`TXPSL
    w 3FFOHP
    'BDFCPPLJOUFHSBUFE7P*1BQQMJDBUJPOGPSJ04

    w 72$IFDLFS
    7PJDF2VPUJFOUBOBMZ[FSGPS1$BOEJ04

    View Slide

  5. "CPVUNF
    w %BJTVLF.VSBTF
    w ,":"$*OD QSFTFOU

    w 5IJTZFBS`TXPSL
    w 3FFOHP
    'BDFCPPLJOUFHSBUFE7P*1BQQMJDBUJPOGPSJ04

    w 72$IFDLFS
    7PJDF2VPUJFOUBOBMZ[FSGPS1$BOEJ04

    w 0OFNPSFUIJOH
    8JMMCFSFMFBTFECFGPSFUIJTYNBT

    View Slide

  6. "CPVUNF
    w BLBUZQFTUFS

    View Slide

  7. "CPVUNF
    w BLBUZQFTUFS
    w IUUQTFBSDIDQBOPSHd5:1&45&3
    w IUUQHJUIVCDPNUZQFTUFS
    w IUUQGBDFCPPLDPNUZQFTUFS
    w IUUQUXJUUFSDPNUZQFTUFS

    View Slide

  8. —.B[EB3PBETUFS
    LOPXOBT.9JOPUIFSDPVOUSJFT

    View Slide

  9. "HFOEB
    w "MJUUMFLOPXMFEHFBCPVU0CKFDUJWF$
    w )PXUPVTF0CKFDUJWF$GSPN1FSM
    w "MJUUMFLOPXMFEHFBCPVU94
    w 4PNFUJQTBCPVU94BOE0CKFDUJWF$
    w *OUSPEVDJOH$PDPBNPEVMFT*`WFDSFBUFE

    View Slide

  10. 0CKFDUJWF$

    View Slide

  11. 0CKFDUJWF$
    w $SFBUFEGPS/FYU4UFQ
    w *U`TDVSSFOUMZVTFEBTQSJNBSZ
    QSPHSBNNJOHMBOHVBHFGPS.BD049
    w *NQMFNFOUFECBTFE$
    "MM$TZOUBYBOEGFBUVSFTDBOCFVTFEJO
    0CKFDUJWF$pMF

    View Slide

  12. 0CKFDUJWF$
    • #import
    int main(int argc, char** argv) {
    NSAutoreleasePool* pool =
    [[NSAutoreleasePool alloc] init];
    // Objective-C code here
    NSLog(@”Hello World!”);
    [pool drain];
    return 0;
    }

    View Slide

  13. 0CKFDUJWF$
    w HDDGSBNFXPSL'PVOEBUJPOGPPN

    View Slide

  14. 0CKFDUJWF$
    w HDDGSBNFXPSL'PVOEBUJPOGPPN
    w MJLFHDDM'PVOEBUJPOGPPD

    View Slide

  15. 0CKFDUJWF$
    w HDDGSBNFXPSL'PVOEBUJPOGPPN
    w MJLFHDDM'PVOEBUJPOGPPD

    w BPVU

    View Slide

  16. 94
    w 'PPYTpMFJTOPUVTFEJSFDUMZGPS$
    DPNQJMFS
    w 'PPYTXJMMDPOWFSU'PPDCZYTVCQQ
    w :PVDBOXSJUF'PPDEJSFDUMZJGZPVXBOU

    View Slide

  17. 'PPD
    • #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__);
    }

    View Slide

  18. QBDLBHF'PP
    •package Foo;
    use strict;
    use XSLoader;
    XSLoader::load __PACKAGE__, $VERSION;
    1;

    View Slide

  19. 3VOJU
    •use Foo;
    Foo::xs_function();

    View Slide

  20. .BLFpMF1-GPS'PPD
    • use inc::Module::Install;
    # some basic descriptions here
    use_ppport '3.19';
    WriteAll;
    w .PEVMF*OTUBMM946UJM

    w 4FFBMTP%BUB.FTTBHF1BDL %BUB".'94 UIBUJTVTJOH
    UIJTQTFVEP94UFDIOJRVF

    View Slide

  21. .BLFpMF1-GPS'PPN

    View Slide

  22. .BLFpMF1-GPS'PPN
    w VTFJOD.PEVMF*OTUBMM
    TPNFCBTJDEFTDSJQUJPOTIFSF
    [email protected]
    [email protected]@[email protected]
    [email protected]\[email protected]^\
    05)&3-%'-"(4GSBNFXPSL'PVOEBUJPO
    ^
    \
    IUUQXXXNBJMBSDIJWFDPNNBLFNBLFS!QFSMPSHNTHIUNM
    "EETPNFSFRVJSFENBDIJOFSZUPTVQQPSUNpMFT
    QBDLBHF.:
    [email protected]\
    NZJOIFSJUFETIJGU461&[email protected] [email protected]

    JOIFSJUFE&0.&44
    N 0#[email protected]&95

    $$$.%
    $$$%-'-"(4
    * 1&[email protected]*/$
    1"45)[email protected]%&'*/&
    %&'*/&
    N
    &0.&44
    JOIFSJUFE
    ^
    [email protected]\
    NZJOIFSJUFETIJGU461&[email protected] [email protected]

    JOIFSJUFE&0.&44
    YTN
    946#1136/
    9413050"3(
    946#11"3(4
    946#[email protected]&953"@"3(4
    YTYTN .7
    YTNN
    &0.&44
    JOIFSJUFE
    ^
    [email protected]\
    NZTFMGTIJGU
    TFMG461&[email protected]

    GPSFBDINZOBNF TFMGMTEJS TFMGDVSEJS

    \

    View Slide

  23. .BLFpMF1-GPS'PPN
    w 4PSSZ

    View Slide

  24. .BLFpMF1-GPS'PPN
    w 4PSSZ

    w 4FF$PDPBbT.BLFpMF1-
    w IUUQTNFUBDQBOPSHTPVSDF5:1&45&3
    $PDPB&WFOU-PPQ.BLFpMF1-

    View Slide

  25. 5IBU`TJU
    w 0CKFDUJWF$JOWPMWFBMM$GVODUJPOTBOE
    GFBUVSFT
    w +VTUSFOBNF'PPDUP'PPN JUDPNQMFUFMZ
    XPSLTCZUIJT.BLFpMF1-
    w "OEPGDBVTF ZPVDBOVTF0CKFDUJWF$
    TQFDJpDTZOUBYJOUIJTpMF

    View Slide

  26. )FMMPN
    • #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
    XS(hello) {
    dXSARGS;
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    NSLog(@"Hello!");
    [pool drain];
    XSRETURN(0);
    }
    XS(boot_Hello) {
    newXS("Hello::hello", hello, __FILE__);
    }

    View Slide

  27. $PQJFTBOEQBTUFTGPS94
    •#include "EXTERN.h"
    #include "perl.h"
    #include "XSUB.h"
    #include "ppport.h"

    View Slide

  28. $PQJFTBOEQBTUFTGPS94
    •#undef Move

    View Slide

  29. $PQJFTBOEQBTUFTGPS94
    •XS(function) {
    dXSARGS;
    // code here
    XSRETURN(0);
    }

    View Slide

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

    View Slide

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

    View Slide

  32. $PQJFTBOEQBTUFTGPS94
    • 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);
    }

    View Slide

  33. $PQJFTBOEQBTUFTGPS94
    • 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);
    }

    View Slide

  34. GPS0CKFDUJWF$BOE1FSM
    w 1FSMTUSJOHUP/44USJOH
    STRLEN len;
    char* c = SvPV(sv, len);
    NSString* str = [NSString stringWithUTF8String:c];
    w /44USJOHUP1FSMTUSJOH
    SV* sv = sv_2mortal(newSV(0));
    sv_setpv(sv, [str UTF8String]);

    View Slide

  35. GPS0CKFDUJWF$BOE1FSM
    w 1FSMOVNCFSUP/4/VNCFS
    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))];
    }
    w /4/VNCFSUP1FSMOVNCFS
    SV* sv = sv_2mortal(newSVnv([n doubleValue]));

    View Slide

  36. GPS0CKFDUJWF$BOE1FSM
    w 4OJQ EFTDSJCFEJONZCMPHMBUFS
    w 1FSMBSSBZUP/4"SSBZ
    w /4"SSBZUP1FSMBSSBZ
    w 1FSMIBTIUP/4%JDUJPOBSZ
    w /4%JDUJPOBSZUP1FSMIBTI

    View Slide

  37. %PO`UGPSHFU
    w FOBCMF/4"VUPSFMFBTF1PPMTDPQFBSPVOE
    ZPVS/4PCKFDUT
    w PUIFSXJTFUIFDPEFXJMMDSBTI

    View Slide

  38. :PVSGSJFOET
    w QFSMEPDQFSMHVUT
    w QFSMEPDQFSMBQJ
    w YDPEFEPDVNFOUBUJPO

    View Slide

  39. $PDPBNPEVMFT

    View Slide

  40. $PDPBNPEVMFT
    w $PDPB&WFOU-PPQ
    w $PDPB(SPXM
    w "OZ&WFOU*NQM$PDPB

    View Slide

  41. $PDPB&WFOU-PPQ
    w QSPWJEFTQFSMJOUFSGBDFGPS$PDPBTFWFOU
    MPPQ /43VO-PPQ
    w BMTPQSPWJEFTUJNFST *0XBUDIFSTBDUT
    XJUIUIBUFWFOUMPPQ
    w :PVDBOIBOEMFFWFOUDBMMCBDLTDPSSFDUMZ
    CZVTJOHUIJTNPEVMF

    View Slide

  42. $PDPB(SPXM
    w 1FSMJOUFSGBDFGPS(SPXMGSBNFXPSL
    w 4VQQPSUDMJDLFWFOUXJUI
    $PDPB&WFOU-PPQ

    View Slide

  43. $PDPB(SPXM
    •use Cocoa::Growl ':all';
    my $installed = growl_installed();
    my $running = growl_running();

    View Slide

  44. $PDPB(SPXM
    • use Cocoa::Growl ':all';
    # register application
    growl_register(
    app => 'My growl script',
    icon => '/path/to/icon.png',
    # or 'http://urlto/icon'
    notifications =>
    [qw(Notification1 Notification2)],
    );

    View Slide

  45. $PDPB(SPXM
    •use Cocoa::Growl ':all';
    # show growl notification
    growl_notify(
    name => 'Notification1',
    title => 'Hello!',
    description => 'Growl world!',
    );

    View Slide

  46. $PDPB(SPXM
    • 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;

    View Slide

  47. "OZ&WFOU*NQM$PDPB
    w "OZ&WFOUBEBQUPSGPS$PDPB&WFOU-PPQ
    w ZPVDBOVTF$PDPBCBTFE"1*JOZPVS
    "OZ&WFOUBQQMJDBUJPO PS"OZ&WFOUXJUIJO
    $PDPBBQQMJDBUJPOT

    View Slide

  48. "OZ&WFOU*NQM$PDPB
    w +VTUEPUIJT
    use AnyEvent;
    use Cocoa::EventLoop;
    # then all anyevent based api use
    Cocoa::EventLoop!

    View Slide

  49. "OZ&WFOU*NQM$PDPB
    • 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;

    View Slide

  50. &OKPZ

    View Slide