Listing One //--------------------------------------------------------------- // PhoneClient.m by Ernest Prabhakar, 1995 // Transliteration of test suite into Objective-C // The only addition is to free strings for the remote case //--------------------------------------------------------------- #import "PhoneDir.h" #ifdef REMOTE #import #endif main(int argc, char* argv[]) { const char* name; const char* number; #ifdef REMOTE // scan subnet for object id theDir = [NXConnection connectToName:dirName onHost:"*"]; if (!theDir) { printf("Server not present.\n"); exit(1); } else { printf("Connected to remote server.\n"); } #else PhoneDir* theDir = [[PhoneDir alloc] init]; #endif // Call server to get number for name, if any. name = "John Doe"; number = [theDir number:name]; // Print out result if (number) { printf("%s's number is %s.\n", name, number); #ifdef REMOTE // For remote case, free returned string free((char*)number); #endif } else { printf("%s does not have a number listed.\n",name); } // do a lookup by number number = "408-555-1212"; name = [theDir name:number]; if (name) { printf("%s's number is %s.\n", name, number); #ifdef REMOTE // For remote case, free returned string free((char*)name); #endif } else { printf("The phone number %s has not been assigned.\n",number); } exit(0); } Listing Two //--------------------------------------------------------------- // ** PhoneDir.h ** by Ernest Prabhakar, 1995 // The protocol and interface declaration for the PhoneDir class. //--------------------------------------------------------------- #import static const char* dirName = "PhoneDirectory"; //--------------------Protocol Declaration---------------------- @protocol PhoneDirectory // Return number given name - (const char*) number:(const char*) name; // Return name given number - (const char*) name:(const char*) number; @end //-------------------Interface declaration---------------------- // Inherits name: and number: from protocol @interface PhoneDir : Object { } // initialization and destruction - init; - free; @end Listing Three //---------------------------------------------------------------------------- // PhoneDir.m by Ernest Prabhakar, 1995 // Wrapper class for the C phonedir functions. It uses the original C code // unchanged to prove a point. Otherwise, the code for the PDO implementation // would be about the same size as original non-distributed code! //---------------------------------------------------------------------------- #import "PhoneDir.h" #include "phonedir.h" @implementation PhoneDir : Object { } //--------------------------------------------------------------- - init { [super init]; phonedir_Initialize(); return self; } //--------------------------------------------------------------- - free { phonedir_Terminate(); return [super free]; } //--------------------------------------------------------------------------- // When the object is invoked over the wire with a string argument, a copy of // the passed string is made. In that case, we have to explicity free the // string. On a local invocation, the string would be a reference from the // caller, and we should not free it. This dichotomy between local and remote // calls--and the different treatment of char* and other pointers--is due // to the limitations of PDO 2.0, and will not be necessary in PDO 3.0. //--------------------------------------------------------------------------- // // Return the phone number, given a customer name. - (const char*) number:(const char*) name { const char* result = phonedir_LookupByName(name); #ifdef REMOTE free(name); #endif return result; } //--------------------------------------------------------------- // Return the customer name, given the phone number. - (const char*) name:(const char*) number { const char* result = phonedir_LookupByNumber(number); #ifdef REMOTE free(number); #endif return result; } @end Listing Four //--------------------------------------------------------------- // PhoneServer.m by Ernest Prabhakar, 1995 // Creates the PhoneDir object & sets it up to service requests. //--------------------------------------------------------------- #import "PhoneDir.h" #import main(int argc, char* argv[]) { id myDir = [[PhoneDir alloc] init]; id myConn = [NXConnection registerRoot:myDir withName:dirName]; printf("Starting server...\n"); [myConn run]; } Example 1: A simple server application. main() { static const char* serverName = "ServerName"; // create and initialize the Server object MyServer* mine = [[MyServer alloc] init]; // register the Server with the nameserver facility NXConnection* conn = [NXConnection registerRoot:mine withName:serverName]; // start servicing requests [conn run]; } Example 2: Client for the simple server. main() { static const char* serverName = "ServerName"; // Get the proxy for the server - scan the entire subnet id serverProxy = [NXConnection connectToName:serverName onHost:"*"]; // Pass two floating-point numbers to server and get a result float result = [serverProxy multiply:7.0 with:5.0]; // Get a proxy for another object vended by the server id objectFromServer = [serverProxy getAnotherObject]; // Pass a string, and get one back char* string = [serverProxy sendAndReturnString:"string pointer"]; } Example 3: (a) @protocol ServerProtocol : InheritedProtocol - multiply:(float) a with:(float) b; - (char*) sendAndReturnString:(const char*) ptr; - (id) getAnotherObject; @end @class MyServer: Object //... @end (b) // Get the proxy for the server id serverProxy = [NXConnection connectToName:server]; // Get a proxy for another object vended by the server id another = [serverProxy getAnotherObject]; Example 4: // Called when this object receives a message that it cannot respond to. // Messages consist of a "selector" (i.e. "forward::") plus arguments. If // forward:: is not defined, then "doesNotRecognize:" is automatically called. // The variable "delegate" is an instance variable of this class. - forward:(SEL)aSelector :(marg_list)argFrame { // if the delegate can handle it, let it. if ( [delegate respondsTo:aSelector] ) return [delegate performv:aSelector :argFrame]; // otherwise, raise the error [self doesNotRecognize:aSelector]; }