Objective-Everything Release 5. Copyright ©1994-1998 by TipTop Software, Inc. All Rights Reserved.
In ObjShell: Double-click on ObjShell.app. Click "Load Perl", and then click "Perl".
In a terminal shell: Run the perl or objperl executable:
perl -e 'use ObjPerl; ...' objperl -e 'use ObjPerl; ...'
The objperl executable is statically linked with the ObjPerl framework. If you want to type commands interactively to the perl interpreter, run objperlsh:
objperlsh perl% use ObjPerl; perl% ...
To run the application kit type:
objperl -e 'use ObjPerl; use AppKit; AppKit::run {interact};'
[This does not work in Windows, due to Windows limitations. In Windows, you have to run ObjShell.app.]
In InterfaceBuilder: Load ObjPalette.palette from /Local/Developer/Palettes/. Click Tools->Objective->Interactor->Interact and select Perl to open an ObjPerl interactor window.
All of the following examples are executed in InterfaceBuilder.
All of the following examples assume that ObjPerl and AppKit modules are imported in the current namespace:
use ObjPerl; use AppKit;
NOTE: To terminate a Perl expression in an interactor so that it is executed in a Perl interpreter, make sure that you terminate it with ';'. You can force execution even when the expression is not complete (unbalanced) by terminating it with ';;'. If you don't want the expression to be executed, even if it is balanced, hit "Shift-Return" instead of "Return".
C functions live in the C namespace. E.g., in an Interactor window, type:
C::NSRunAlertPanel("Perl","Hello World!",nil,nil,nil);
To read a value, simply "call" it by name, or simply access it as a Perl global variable:
perl% (new C 'NSArgc')->FETCH; 3 perl% (new C 'NSArgv')->FETCH; ^[3*]@0x... perl% (new C 'NSArgv')->FETCH->FETCH; ['/NextDeveloper/Apps/InterfaceBuilder.app/InterfaceBuilder', '-MachLaunch', '10 40'] # Note: NSApp is conveniently accessible as $NSApp perl% $NSApp; <IB:0x...> # Define global NSGenericException, and then access it # (it is a string with contents "NSGenericException") perl% $d=new C 'NSString*', 'NSGenericException'; ^@@NSGenericException perl% $d->define('NSGenericException'); perl% $x=(new C 'NSGenericException')->FETCH; <NSConstantString:0x...> perl% print "$x\n"; NSGenericException # Link C datum $d to be accessible as Perl global $MyVar perl% $ObjPerl::interp->linkDatumEncoding_atAddress_asVariableName_( %---> $d->typeof->encoding, $d, '$::MyVar'); perl% $MyVar; <NSConstantString:0x180c4944> perl% print "$MyVar\n"; NSGenericException
Use Perl message syntax:
perl% $NSApp->class; IB perl% $NSApp->showInfoPanel(nil);
# Construct an object: perl% $x=NSObject->alloc->init->autorelease; <NSObject:0x...> # ObjPerl automatically takes care of memory management. # In this example, although the object is (auto)released, it is not yet deallocated, # since the Perl variable x holds a reference to the object. perl% print $x->description,"\n"; <NSObject: 0x...> perl% undef $x; # The object is now really gone.
# ObjPerl also detects when objects become illegal. perl% $x=NSObject->alloc->init->autorelease; <NSObject:0x...> perl% $x->release; perl% $x->description; ObjPerl::msg_send: Dealloc'ed object at ...
Simply define a category on a class.
perl% extend NSObject, { %---> '-(void)sayHelloTo:(NSString*)name' => sub { %---> C::NSRunAlertPanel('Perl',"Hello $_[2]", nil,nil,nil); %---> }}; NSObject perl% $NSApp->sayHelloTo(C::NSFullUserName());
Note: "extend" is a synonym for "category".
Classes are defined using the "class" command. Instance variables and method prototypes are specified using the ObjC syntax.
perl% class 'MyObject', 'NSObject', ' %---> NSString *aString; %---> id anObject; %---> char *aCString; %---> '; MyObject perl% category MyObject, { %---> '-(void)dealloc' => sub { %---> print "@_\n"; %---> my($self,$_cmd)=@_; %---> $self->{'aString'}=nil; %---> $self->{'anObject'}=nil; %---> $self->{'aCString'}=undef; %---> $self->SUPER::dealloc; %---> }, %---> %---> '-(void)setStringValue:(NSString*)s' => sub { %---> print "@_\n"; %---> my($self,$_cmd,$s)=@_; %---> $self->{'aString'}=$s; %---> }, %---> %---> '-(NSString*)stringValue' => sub { %---> print "@_\n"; %---> return $_[0]->{'aString'}; %---> }, %---> %---> # etc %---> }; MyObject perl% $obj=MyObject->object; <MyObject:0x...> perl% $obj->setStringValue('Hello World'); <MyObject:0x...> setStringValue: Hello World perl% $obj->stringValue; <MyObject:0x425f00> stringValue <NSInlineCString:0x...> perl% "".$obj->stringValue; <MyObject:0x...> stringValue 'Hello World' perl% (new C $obj)->FETCH; [MyObject, <NSInlineCString:0x...>, nil, undef] perl% undef $obj; <MyObject:0x...> dealloc
Objective-Everything lets you define instance-specific instance methods.
perl% $x=MyObject->object; <MyObject:0x...> perl% $y=MyObject->object; <MyObject:0x...> perl% extend $x, { %---> '-(const char *)sayHello' => sub { %---> return "Hello from $_[0]"; %---> }}; @MyObject@... perl% $x->sayHello; 'Hello from <@MyObject@...:0x...>' perl% $y->sayHello; <MyObject:0x...> does not respond to sayHello ... perl% $x->class; MyObject perl% $y->class; MyObject # Override -showInfoPanel: of CGlob.NSApp. # First, find out what the -showInfoPanel: prototype is perl% print unparse($NSApp); @interface IB : NSApplication <IB_Full> // Subclasses: None { ... } ... - (void)showInfoPanel:(id)a0; ... @end # Or, simply: perl% Info::methods $NSApp->class, 'showInfo*'; '- (void)showInfoPanel:(id)a0;' # Now, override -showInfoPanel: to run an alert panel, and then invoke # the previous (in this case ObjC) method implementation. perl% extend $NSApp, { %---> '-(void)showInfoPanel:(id)sender' => sub { %---> C::NSRunAlertPanel('Perl', 'About to show IB info panel',nil,nil,nil); %---> $_[0]->EX::showInfoPanel($_[2]); %---> }}; @IB@100864
Now, click Info->InfoPanel.
Click Document->NewApplication. Drag the ObjPerl interpreter object from ObjPerl palette into the object suitcase. Drag a button into the window. Ctrl-connect the button to the interpreter object, and select the newWInteractor: action.
Now, when you run the nib file by clicking Document->TestInterface, when you click the button, you will get an interactor window in which you can type commands to be executed by the interpreter.
Add another button into the window. Ctrl-drag from the interpreter instance to this button. Type "but" in the connections inspector. Ctrl-drag from the interpreter instance to the "My Window" window title bar. Type "win".
Run the interface (Cmd-r or click Document->TestInterface). Hit the button which opens the interactor window. Type:
perl% $but->setTitle('Hello');
perl% $win->setTitle('World');
Quit the TestInterface mode. Close the nib file (save it if you like).
In this example we build a simple expression calculator which simply uses the Perl eval command to evaluate mathematical expressions.
Click Document->NewApplication. Drag the TextField object into window "My Window". Change it to look something like:
Drag the Code object from ObjPalette into the object suitcase. Ctrl-Alt-drag from the code object to the result field. Type "resultField".
In the implementation inspector, select Perl. The code object will then use the Perl interpreter for evaluation. Hit "+" and implement the action as follows:
use ObjPerl; extend $self, { '- (void)action:(id)sender' => sub { my($self,$_cmd,$sender)=@_; my $r=eval($sender->stringValue) || $@; (xget $self, 'resultField')->setStringValue($r); }, };
Ctrl-drag from the "Expr:" field to the code object, and
connect it to the "executeCode:" action.
Test the interface: Type "1+2" and hit Return.
Type "sin(1)" and hit Return.
Close the nib file (save it if you like).
The Code object lets you implement interpreted action methods without having to implement a new class. In general, the Code object is useful for implementing simple actions.
Another way of implementing actions is to directly extend an instance with an action method. In this example we implement the same calculator as in the previous example.
Create a window with fields, like in the previous example.
Drag the ObjPerl interpreter from the ObjPerl palette into the object suitcase. Connect fields as globals in the interpreter with names "rfield" and "efield" (Ctrl-drag from the interpreter to each field, and type the field name).
Since we want to define an action for "efield", double-click on the "efield" in the ConnectionInspector. Click "Create" when you are asked whether to create action implementation.
Implement the action as follows:
use ObjPerl;
extend $efield, { '-(void)action:(id)sender' => sub { my $r=eval($_[0]->stringValue); if($@) { C::NSRunAlertPanel 'Perl Error', "$@", nil,nil,nil; return; } $rfield->setStringValue($r) }};
Run and test the interface.
Note: You should not define a class in a NIB file (in interpreter startup code, or in a code object) if the NIB file contains an instance of that class, because it is not possible to ensure that the code is executed before the instance is instantiated.
Yet another way of implementing actions is to directly extend an instance with an action method. In this example we implement the same calculator as in the previous example.
Create a window with the fields, like in the previous example.
Double-click on the "Expr:" field to select it. Connect xvar "resultField" of the "Expr:" field to the "Result:" field: Ctrl-Alt-Drag from the "Expr:" field to the "Result:" field, type "resultField", and hit Return.
Since we want to define an action for the "Expr:" field, double-click on the "Expr:" field to select it. In the Implementation inspector select "Perl", hit "+", and implement the action as follows:
use ObjPerl; extend $self, { '- (void)action:(id)sender' => sub { my($self,$_cmd,$sender)=@_; my $r=eval($sender->stringValue) || $@; (xget $self, 'resultField')->setStringValue($r); }, };
Note that there you should not use @interface and @implementation constructs. Just include your method definitions and optional instance variable declarations. This is similar to how you define WebObject components in WebScript.
Run and test the interface. It should behave exactly the same as the previous example.
In a terminal shell, type:
robjperlsh IBInterp
This will give you access to the ObjPerl interpreter in InterfaceBuilder. You can now issue any command to this interpreter; e.g., type: $NSApp->showInfoPanel(nil);
To set a remote interpreter connection in InterfaceBuilder: Drag an Interactor object from the ObjPalette into the object suitcase. Drag a button into the window. Connect the button to the interactor, so that it sends the "run:" message. In the attribute inspector for the interactor, click the Remote switch, so that it is ON, enter "IBInterp" into the connection field, enter "ObjPerlInterp" into the interpreter field, and hit return. Now when you run the nib file, and hit the button, the interactor will connect to IB (itself)...
Type "AppKit::browse $NSApp" in an interactor window, and browse away!
To run the browser from a Terminal shell:
objperl -e 'use Objperl; use AppKit; AppKit::run {browse $NSApp}'
Use ProjectBuilder to create an application project, and use InterfaceBuilder to create nib files. Make sure that you link the application with ObjCore and ObjAppKit frameworks. When you build and run the application, Objective-Everything will get initialized...
Note: Under Windows, you need to reference a symbol in each of the frameworks that you link with. E.g., in YourApp_main.m, make sure you do:
#import <ObjAppKit/ObjAppKit.h>
int main(int argc, const char *argv[]) { {
[TTInterp class]; [TTApplication class]; return NSApplicationMain(argc, argv); }
See UsingPB.rtfd for how to include ObjPerl files in the project, how to manage and edit them using PB.
If you have a NIB file which you want to run as an application, you can simply run objperl as:
objperl -e 'use ObjPerl; use AppKit; AppKit::run {} {"nib" => "/your/nib"}'
Statically link your application with the ObjCore and ObjAppKit frameworks; or, dynamically load these frameworks:
[[NSBundle bundleWithPath:@"/LocalLibrary/Frameworks/ObjAppKit.framework"]
principalClass];
Then, at runtime, to open an interactor window:
[TTInterp newWInteractor:nil];
or, send the newWInteractor: message to the first responder, e.g., via a button, or a menu item. This will give you a starting point for interactively issuing commands to your app...
For example, to run Objective-Browser inside EOModeler:
objmeddle /System/Developer/Applications/EOModeller.app/EOModeler
You can now run an interactor from the Objective menu (in Tools), or run ObjBrowser, etc.
Read the documents in ObjCore/Documentation/Concepts to become familiar with the general Objective-Everything concepts. Read other documents in this directory to get familiar with ObjPerl.
Also, make sure that you look at the examples which are included in each Obj<Lang>.framework/Resources/Examples directory.