Documentation
From my personal library, The Internet

man page:


SYNOPSIS

           use Foundation;

           $s1 = NSString->stringWithCString_("Hello ");
           $s2 = NSString->alloc()->initWithCString_("World");
           $s3 = $s1->stringByAppendingString_($s2);
           printf "%s\n", $s3->cString();


SUMMARY

       The PerlObjCBridge module supports creating and messaging Objective-C
       objects from Perl programs, allowing Cocoa objects in Apple Computer's
       Mac OS X to be directly manipulated from Perl. In addition, Perl
       objects can be messaged from Objective-C, making it possible for Perl
       objects to function as Cocoa delegates and as targets of notifications
       and other Cocoa call-back messages. Perl programs can take advantage of
       Cocoa's Distributed Objects mechanism to support messaging between Perl
       objects and Objective-C objects (or other Perl objects) in different
       address spaces, possibly on different machines.


LIMITATION

       This version of PerlObjCBridge does not directly support writing GUI
       Cocoa applications in Perl. Consult http://www.source-
       forge.net/projects/camelbones for a freeware package that supports GUI
       Perl/Cocoa apps.


DESCRIPTION

       Using PerlObjCBridge, Perl programs can reference Objective-C objects
       in a manner similar to references to native Perl objects. The Objec-
       tive-C objects must inherit from the NSObject root class in the Mac OS
       X Foundation framework (which is true for Cocoa objects). In Objective-
       C an object is accessed via an object identifier that is implemented as
       a pointer to a structure containing the object's instance data. PerlOb-
       jCBridge represents an Objective-C object as a Perl reference to a
       scalar value that contains the Objective-C ID. For example, if an
       Objective-C object has an ID with value 0x12345678, then PerlObjCBridge
       represents that object as a reference to a scalar with value
       0x12345678. The Perl reference is "blessed" into a Perl class that has
       the same name as the Objective-C class. The Perl inheritance mechanism
       is then used to route any messages sent to the object from Perl through
       the PerlObjCBridge extension module and ultimately to the Objective-C
       object. The return values of the Objective-C messages are similarly
       routed back through the bridge where they are converted into Perl
       return values.

       It is also possible to use Perl objects in places where Cocoa methods
       normally take Objective-C arguments. For example, one can register Perl
       objects to receive NSNotifications, in which case the perl objects pro-
       vide the notification handling methods that are asynchronously messaged
       by NSNotificationCenter when interesting events occur. As another exam-
       ple, a Perl object can be registered as a server object via NSConnec-
       tion, after which Objective-C or Perl objects in other address spaces
       can send messages to the server object via the Distributed Objects
           $anObject->arg1_arg2_($x, $y);

       Contrast the following Objective-C code fragment with its Perl analogue
       in the synopsis at the top of this man page:

           #import <Foundation/Foundation.h>

           NSString *s1 = [NSString stringWithCString:"Hello "];
           NSString *s2 = [[NSString alloc] initWithCString:"World"];
           NSString *s3 = [s1 stringByAppendingString:s2];
           printf("%s\n", [s3 cString]);

       To send a message to an Objective-C class, one uses the syntactic form
       ClassName->method(...args...). For example, one can send the "default-
       Manager" message to the NSFileManager class as follows:

           $defMgr = NSFileManager->defaultManager();

       An important special case of a class method is a "factory" method that
       constructs a new instance of a class:

           $array = NSMutableArray->array();

           $string = NSString->stringWithCString_("Hi there");

       The NSString factory method illustrates how PerlObjCBridge passes Perl
       strings to Objective-C as char *'s.

       To send a message to an Objective-C object, one uses the syntactic form
       $object->method(...args...). If $array is a reference to an
       NSMutableArray then one can add the NSString referenced by $string by
       sending $array the "addObject:" message:

           $array->addObject_($string);

       Message sends can be chained from left to right:

           $hostName = NSProcessInfo->processInfo()->hostName();

       In the above example, the object returned by NSProcessInfo->process-
       Info() is in turn sent the hostName message.


USING COCOA FRAMEWORKS

       PerlObjCBridge automatically generates a bridge module for the Founda-
       tion framework that is included with the Cocoa environment in Mac OS X.
       This bridge module is created when PerlObjCBridge is built. The bridge
       module for a framework causes that framework to be dynamically loaded
       into the Perl program's address space. In addition Perl packages are
       created for each of the Objective-C classes in the framework so that
       the Objective-C classes exist in the Perl name space.

       To access a framework from Perl "use" its bridge module. For example,
       means of DO. The system consists of a Perl client program, a Perl
       server program, and a Perl XSUB module that provides the glue between
       the Perl programs and DO. The XSUB module is initially created by run-
       ning the following  command:

           h2xs -A -n AddSystem

       An AddSystem directory is created with these files:

           AddSystem.pm
           AddSystem.xs
           Changes
           MANIFEST
           Makefile.PL
           test.pl

       Edit the Makefile.PL DEFINE entry to add the -ObjC flag:

           'DEFINE'            => '-ObjC', # e.g., '-DHAVE_SOMETHING'

       Modify the contents of AddSystem.pm to contain:

           package AddSystem;

           @ISA = qw(Exporter DynaLoader);
           @EXPORT = qw( );
           $VERSION = '1.0';
           bootstrap AddSystem $VERSION;

           use Foundation;

           1;

       and modify AddSystem.xs to have the contents:

           #include <mach-o/dyld.h>
           #include "EXTERN.h"
           #include "perl.h"
           #include "XSUB.h"
           #ifdef Move
           #undef Move
           #endif Move
           #ifdef DEBUG
           #undef DEBUG
           #endif DEBUG
           #ifdef I_POLL
           #undef I_POLL
           #endif I_POLL
           #import <Foundation/Foundation.h>

           @interface AddClient : NSObject
           @end

       AddSystem.xs defines "dummy" AddClient and AddServer Objective-C
       classes that implement the methods that the Perl client and server will
       provide. These dummy Objective-C classes are needed in this case
       because there would otherwise not be enough information for the DO run-
       time system to determine the numbers, types, and sizes of the method
       arguments and return values. These dummy Objective-C implementations
       are usually only needed when DO is being used and the Perl program does
       not link against any libraries that contain objects that already imple-
       ment the methods. The actual method bodies are irrelevant and can be
       trivially defined to return 0 or NULL. In the case of methods that
       return void, the dummy methods can have empty bodies.

       After modifying Makefile.PL, AddSystem.pm, and AddSystem.xs, execute
       the following commands (as root or as an admin user):

           perl Makefile.PL
           make install

       Now add two Perl programs to the AddSystem directory. The first program
       is addServer:

           #!/usr/bin/perl

           use AddSystem;

           package AddServer;
           @ISA = qw(PerlObjCBridge);
           @EXPORT = qw( );

           PerlObjCBridge::preloadSelectors('AddClient');

           sub new
           {
               my $class = shift;
               my $self = {};
               bless $self, $class;
               return $self;
           }

           sub addNumbersForClient_
           {
               my($self, $client) = @_;
               my $first = $client->firstNumber();
               my $second = $client->secondNumber();
               return int($first + $second);
           }

           $server = new AddServer;
           $connection = NSConnection->defaultConnection();
           $connection->setRootObject_($server);
           $connection->registerName_(NSString->stringWithCString_("AddServer"));
           package AddServer;
           @ISA = qw(PerlObjCBridge);
           @EXPORT = qw( );

       cause the AddServer package to inherit from PerlObjCBridge. As a conse-
       quence, messages to and from AddServer objects will be routed through
       PerlObjCBridge.

       The line:

           PerlObjCBridge::preloadSelectors('AddClient');

       instructs PerlObjCBridge to pre-cache all method selectors for the
       Objective-C class AddClient. By doing this, PerlObjCBridge is "primed"
       with the information needed to send messages to objects of class Add-
       Client.

       After a standard "new" constructor method, there is a addNumbersFor-
       Client_ method that provides the service vended by the AddServer class.
       The method name "addNumbersForClient_" corresponds to the Objective-C
       selector "addNumbersForClient:", which has a dummy implementation in
       AddSystem.xs. In addition to the standard $self argument, addNumbers-
       ForClient_ takes a second argument $client which is a reference to the
       invoking client object. The client object is then sent the messages
       "firstNumber" and "secondNumber", each of which returns an integer. The
       server adds the two numbers and returns the result.

       The lines:

           $server = new AddServer;
           $connection = NSConnection->defaultConnection();
           $connection->setRootObject_($server);
           $connection->registerName_(NSString->stringWithCString_("AddServer"));

       create a new AddServer object and set it as the root object of a DO
       connection, registered with the name "AddServer". Clients can then look
       up the name "AddServer" to connect to this object.

       The final line:

           NSRunLoop->currentRunLoop()->run();

       puts addServer into a event loop, waiting for incoming connections from
       clients.

       The second program, addClient, consists of:

           #!/usr/bin/perl

           use AddSystem;

           package AddClient;

           sub firstNumber
           {
               my($self) = @_;
               return $self{'firstNumber'};
           }

           sub secondNumber
           {
               my($self) = @_;
               return $self{'secondNumber'};
           }

           die "usage: perlClient <firstNumber> <secondNumber>\n" unless @ARGV == 2;

           # create client
           $client = new AddClient (@ARGV);

           # create connection to server
           $name = NSString->stringWithCString_("AddServer");
           $server = NSConnection->rootProxyForConnectionWithRegisteredName_host_($name, 0);
           if (!$server or !$$server) {
               print "Can't get server\n";
               exit(1);
           }
           $server->retain();

           printf "%d\n", $server->addNumbersForClient_($client);

       Make sure that the line "#!/usr/bin/perl" does not contain leading
       whitespace.

       The AddClient methods "firstNumber" and "secondNumber" implement the
       call-back methods invoked by the AddServer. The lines:

           $name = NSString->stringWithCString_("AddServer");
           $server = NSConnection->rootProxyForConnectionWithRegisteredName_host_($name, 0);
           if (!$server or !$$server) {
               print "Can't get server\n";
               exit(1);
           }
           $server->retain();

       results in $server being assigned a DO "proxy" object for the AddServer
       object in the addServer program. Any messages sent by the client will
       by forwarded by the DO proxy to the actual AddServer object in the
       addServer address space.

       The final line:

           printf "%d\n", $server->addNumbersForClient_($client);


       Next run the server in one shell:

           addServer

       then the client in another shell:

           addClient 1 2
           3


AUTOMATIC STRING CONVERSION

       For convenience, PerlObjCBridge automatically converts Perl strings
       into NSString Objective-C objects when an NSObject is expected as the
       argument to an Objective-C method. For example, suppose an Objective-C
       dictionary is created:

           $dict = NSMutableDictionary->dictionary();

       The dictionary method "setObject:forKey:" expects the key argument to
       be an NSString and the value argument to be any NSObject. The following
       automatically converts both "aKey" and "aValue" to NSStrings and then
       inserts the pair into the dictionary:

           $dict->setObject_forKey_("aValue", "aKey");

       The value can be retrieved as follows, where "aKey" is again automati-
       cally converted to an NSString:

           $value = $dict->objectForKey_("aKey");
           printf "value is %s\n", $value->cString();

       Note that the return value assigned to $value is a reference to an
       NSString and is not automatically converted to a Perl string. The auto-
       matic conversions occur only from Perl strings to NSStrings for Objec-
       tive-C method arguments. NSStrings return values are not automatically
       converted to Perl strings.

       Automatic conversion also occurs when a Perl string is passed as an
       argument to a method that expects an Objective-C selector. For example,
       the "performSelector:" message can be sent to any NSObject. The argu-
       ment to the "performSelector:" message must be an Objective-C selector.
       In Objective-C, one can copy an existing NSString "origString" by ask-
       ing it to perform the "copy" selector:

           copy = [origString performSelector:@selector(copy)];

       This is equivalent to:

           copy = [origString copy];

       In Perl the selector form can be executed as:

       Objective-C method receives nil for that argument. In the following
       example, the Objective-c method "arg1:optionalArg:" would receive nil
       as its second argument.

           MyClass->arg1_optionalArg_($obj, 0);

       The special value "undef" can also be used:

           MyClass->arg1_optionalArg_($obj, undef);

       When an Objective-C method returns nil, the corresponding Perl return
       value is a reference to a zero-valued scalar. This return value can
       subsequently be passed as an argument to an Objective-C method. In the
       following example, if "aMethod" returns nil then "arg1:optionalArg:"
       would receive nil as its second argument:

           MyClass->arg1_optionalArg_($obj, YourClass->aMethod());

       To determine whether an Objective-C method returned nil one should test
       both the Perl reference and its referent. The referent will be zero-
       valued when the Objective-C method returned nil, but it is also possi-
       ble for the reference itself to be undefined (for example, when the
       method raised an NSException, as discussed below). The following exam-
       ple illustrates the use of an Objective-C NSEnumerator object to print
       the elements of an NSArray. In Objective-C, the enumerator returns nil
       after the last object in the array has been enumerated. In the Perl
       loop, both the reference $obj and the referent $$obj are tested in the
       loop condition. Under normal circumstances looping ends when $$obj
       becomes zero-valued, indicating the enumerator returned nil.

           $enumerator = $array->objectEnumerator();
           while ($obj = $enumerator->nextObject() and $$obj) {
               printf "%s\n", $obj->description()->cString();
           }


EXCEPTION HANDLING

       NSExceptions that are raised as a result of messages sent by Perl pro-
       grams to Objective-C objects are dealt with as follows. PerlObjCBridge
       has a built-in NSException handler that writes the message selector,
       the class of the target object, and the NSException name, reason, and
       userInfo to standard error. By default, the built-in NSException han-
       dler then dies with a message. The function PerlObjCBridge::setDieOnEx-
       ceptions() can be used to control the latter behavior. Invoking set-
       DieOnExceptions() with an argument of 0 will cause the built-in excep-
       tion handler to issue a warning and return without dying, whereas a
       non-zero argument (or no argument) will cause the built-in exception
       handler to die. In the case where the built-in exception handler
       returns with a warning, the original message that caused the exception
       returns undef.

       Alternatively, the Perl program can set its own exception handler by
       calling PerlObjCBridge::setNSExceptionHandler() with a single argument

       The example below stores the original exception handler, sets a new
       exception handler, provokes an NSException by attempting to set a dic-
       tionary entry with a nil key and a nil value, and then restores the
       original exception handler.

          sub myHandler
          {
              my($sel, $pkg, $name, $reason, $userInfo) = @_;
              print "NSException raised!\n";
              print "selector:  $selector\n";
              print "package:   $package\n";
              print "name:      $name\n";
              print "reason:    $reason\n";
              print "userInfo:  $userInfo\n";
          }

          $oldHandler = PerlObjCBridge::getNSExceptionHandler();
          PerlObjCBridge::setNSExceptionHandler(\&myHandler);
          $dict = NSMutableDictionary->dictionary();
          $dict->setObject_forKey_(0, 0);
          PerlObjCBridge::setNSExceptionHandler($oldHandler);

       This results in myHandler printing the output:

          NSException raised!
          selector:     setObject:forKey:
          target class: NSCFDictionary
          name:         NSInvalidArgumentException
          reason:       *** -[NSCFDictionary setObject:forKey:]: attempt to insert nil key
          userInfo:


LARGE NUMERIC VALUES

       PerlObjCBridge assumes no Perl support for 64-bit integers. When an
       Objective-C method has a 64-bit integer return type (i.e., long long or
       unsigned long long) and the result of invoking that method is a return
       value that is too large (i.e., >= 2^^31) or too small (<= -(2^^31)) to
       be represented in Perl as a signed integer then the value is returned
       as a Perl double. Similarly, when a parameter to an Objective-C method
       is a long long or unsigned long long then the type of the Perl argument
       value is examined. If the argument value is a Perl integer then its
       value is passed directly to the Objective-C method in long long or
       unsigned long long form (coercing in the unsigned case). Otherwise if
       the argument value is a Perl double then it is coerced to the appropri-
       ate long long or unsigned long long form before it is passed to the
       method.

       Similar considerations apply to 32-bit unsigned longs and unsigned
       ints. When an Objective-C method has a 32-bit unsigned long or unsigned
       int return type and the result of invoking that method is a return
       value that is too large (>= 2^^31) to be represented in Perl as a
       signed integer then the value is returned as a Perl double. When a
       (this is the default behavior). Calling setDieOnErrors() with an argu-
       ment of zero allows the program to print a warning message but not die
       after such an error.


BUGS AND LIMITATIONS

       PerlObjCBridge should take advantage of Perl support for 64-bit inte-
       gers if available. Feel free to fix this.

       When structs are passed by value, sometimes pointers embedded in the
       structs get mangled. It is better to pass structs by reference if they
       contain embedded pointers.

       Varargs-style messaging is not supported. This is unfortunate, but it's
       due to the lack of varargs support in NSInvocation and NSMethodSigna-
       ture. Fix that and it should be easy to support varargs messaging in
       PerlObjCBridge.

       Access to functions, variables, and other non-object-oriented con-
       structs exported by libraries containing Objective-C is not currently
       supported. It seems dubious that those things are exported as C-level
       constructs to begin with, when they could/should be Objective-C class
       methods. One possible workaround is to create an XSUB that provides
       Objective-C "covers" for these items. For example, if a library exports
       a variable:

           extern int GreatBigFoo;

       then an XSUB with a cover might define:

           @interface Covers: NSObject
           + (int)GreatBigFoo;
           @end

           @implementation Covers
           + (int)GreatBigFoo
           {
               return GreatBigFoo;
           }
           @end

       Then the value of the variable could be accessed in Perl:

           $gbf = Covers::GreatBigFoo();


SEE ALSO

       perl(1).  Mac OS X: /Developer/Documentation/Cocoa/ObjectiveC Mac OS X:
       /Developer/Documentation/Cocoa/Reference/Foundation



perl v5.8.6                       2004-09-13                 PerlObjCBridge(3)

Man(1) output converted with man2html