discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

PDO replacement attempts, or How to setReturnValue of an NSInvocation


From: OSX Developer
Subject: PDO replacement attempts, or How to setReturnValue of an NSInvocation
Date: Sun, 6 Jan 2002 00:58:45 -0800

Hello I have been trying to replace the no longer properly supported PDO 
Portable Distributed Objects System in OSX Server 10.1.2.
I thought someone here might be able to help or explain if this works in 
GnuStep, which might help me to understand the bugs in OSX or if there really 
is a way to do it in gnustep somehow maybe (I am not sure).

I have a summary and detailed description of my attempts and problems which I 
will appemt that was intended for another newsgroup for osx developers at 
omniweb. [So Sorry if this is the wrong place but there are few options 
available to try otherwise.]

Basically I have my own Connection DistantObject, with a tri-set of tools; a 
hub-server, a server, and client tool. All integrated to replace PDO.

I was able to send an NSInvocation via a socket as a data stream after 
Archiving and Unarchiving the Invocation (via NSArchiver and NSUnarchiver).
The real problems come when returning the post-invoked NSInvocation or just 
simply trying to set the return value, setReturnValue:.

Problems are setReturnValue does not set the return value in a usable way. 
[returnalueString setString:[server newPDOtakeStringAndReturnString:@"value to 
send"]];
In OSX it complains saying that a NSCFString does not understand the method 
selector 'length', yet I set it to a string [anInvoaction 
setReturnValue:[NSString stringWithString:@"The Return Value"]];, a thousand 
ways but no luck.
Further the Archiver failed to archive any NSInvoaction with more then one 
argument parfing like this @@ I do not understand idid @@ what type is that. 
The archiving or Unarchiver also failed to properly archive the return values 
or Mutable return arguments, even when forcing the Protocol to have inout 
delarations which is the default anyway.
For a further deeper explaination I will append the other detail description.
So I did understand that even though getReturnValue: and setReturnValue: are 
both using :(void *)buffer arguments, and the development tools inspector shows 
all types of values pointing to this buffer. One can get the value via a 
refernce to a *(id *) but I just do not understand how to set the return value 
to an id NSString or NSDictionary etc.

Summation of following Bugg Description.-
________________________________________________
NSInvocation is not able to set the return value (setReturnValue:) in a usable 
way, or requires proper documentation.

NSArchiver and NSUnarchiver both have problems when dealing with NSInvocations 
(and using them in Distant Object Message). NSArchiver seems to fail in 
fowrardInvocation: calls of an Application and errors on multiple argument 
method signatures in an Objective-Tool, while the Unarchiver seems unable to 
unarchive the return value of an NSInvocation (0x0 is all there is, so it's a 
separate problem the the setReturnValue issue, but could be related).

[see detailed description below for more information about these problems, or 
at least my attempts to replace the reportedly no longer support yet critical 
PDO (Portable Distributed Objects) system.
________________________________________________

[The Replacement Classes will be called NEW_*Class* for this explanation.]
After building an entire replacement for PDO (Portable Distributed Objects), I 
have discovered a few technical problems. [Needed has been a NEW_Connection to 
replace NSConnections, a NEW_DistantObject to replace NSDistantObject, and also 
I have couple of socket classes that NEW_Connection uses.]
As far as programs I have (so far for now) a Hub Tool that allows Servers to 
register a name and the hub keeps track of a port number and the IP, this can 
be global [I believe the old system must have used the broadcast address, but 
for my needs a more global approach is needed (besides being an easier short 
cut for now) and therefor a central Hub process is required or at least a list 
to try in some order or to check all of. Then one might have a concept of a 
Master Hub and Slave Hubs etc.], and eventually a secure socket layer (SSL) 
would be included, if needed beyond the local network. Lots more is needed here 
only when and if the rest of it works right, and is otherwise still needed that 
is true PDO returns.)
Next comes the Server Tool that connects to the Hub and Requests to Register a 
name, the hub returns the next port for that IP and the server starts a 
NEW_Connection which runs a NEW_socket that waits for a client to connect to it.
Then the Client Tool asks the Hub for the IP and port of a server that is 
serving a NEW_Connection for the registered name. It gets this information and 
establishes a NEW_Connection with the server. (They confirm the connection to 
each other.)

[Finally the magic part comes next, since this is built on and for Objective-C, 
and it is intended to replace the no longer working properly or suppose to be 
supported ever again PDO (that made NeXT useful, important, and of any value to 
me.) The replacement must follow the form of NSConnections, NSDistantObjects, 
etc. but most importantly it must use the NeXT (now seemingly unstably sketched 
and owned by Apple) Classes NSInvocation and NSArchiver (the archiver seems to 
need replacing and that might be basically possible in the case of 
NSInvocations at some point, but the NSInvocation is limited or appears buggy, 
hence this document or bugg inquiry it is eventually intended for.]

The Client Tool has a proxy or NEW_DistantObject that has a/the Protocol of the 
Served Object (I have tried variations of 'inout' [default] etc. and other type 
declarations documented for protocols intended for just such a situation, to no 
avail so far.)
Now the client sends a message to the Proxy(NEW_DistantObject) [This 
NEW_DistantObject is required because I have a NEW_Connection using a 
NEW_Socket, and NSDistantObject does not have a usable Connection otherwise.]
Say like this ...
[server takeStringAndReturnString:(NSString *)someString];
The Proxy must implement methodSignatureForSelector and for now I use a method 
called setRootObject: to make sure the method signature is of the correct type 
(I can see that this is slightly different then what was required with the 
original PDO but for now it's a good work-around [and not a/the problem].)

- (void)setRootObject:(id)rootObject {
    rootObj = rootObject;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    return [rootObj methodSignatureForSelector:aSelector];
}

This validated the method signature that the proxy does not handle other then 
to forward the invocation to the Distant Object via the NEW_Connection's 
NEW_socket estsablished as described before.

Up next is the - (void)forwardInvocation:(NSInvocation *)anInvocation; method. 
Here now one would archive the invocation for transmitting as a Data Object. To 
do that I use NSArchiver something like this ...
NSData *archivedInvocationAsData = [NSArchiver 
archivedDataWithRootObject:(id)anInvocation];
Okay now I writeData: and wow guess what the data actually shows up at the 
Server Tool, is Unarchived with ...
NSInvocation *theInvocation = [NSUnarchiver 
unarchiveObjectWithData:invocationAsData];

Then it is invoked with ...
    [theInvocation invokeWithTarget:rootObj];

Awesome it actually works to trigger an Invocation remotely (so far, in this 
limited way.)

Clearly the simplest next step is to re-archive the invocation with it's return 
values etc. and send it back via ...
returnInvocation = [NSArchiver archivedDataWithRootObject:theInvocation];
through the NEW_Connection's NEW_Socket (writeData:).
Back at the Client it waited via readData: for the return invocation (post 
invoke), it then Unarchives it and would likely just replace the original 
invocation with the return invocation. This does not work, the NSInvocation has 
a return value, and that value is readible as the getReturnValue:(void *)buffer 
via *(id *)buffer. Even if you use retainArguments at the server side, observe 
'inout' [default] definitions in the Protocol description, etc. still nothing 
seems to work rightas far as returning or even setting the 'return value' or 
changing transported arguments Arguments.

Now originally on the Server side I was able to use the extremely limited 
getReturnValue:(void *)buffer method to get the pointer (always with a length 
of four). Only from a Chinese Web page did I discover that to use this value 
one must use *(id *)buffer to reference the NSString/NSObject there.

My problem mainly is when I try to set the return value (or unarchive the 
return values) in an invocation I run into problems. One is suppose to use the 
setReturnValue:(void *)buffer method.
I can use it I can observer in the debugger value inspector the values setting 
(there is one of ever type pointing to the same thing or something, of course 
Objective-C limits the access of these inner values and provides only the 
setReturnValue:(void *)buffer. I have yet to try a subclass that would 
hopefully be able to access them as public values, but this is doubtful, and 
suggests that NSInvocation would need Class Extensions but basically this means 
it's buggy and there must be a better way.

Now to try and explain all the problems that occur ...
To start we must go back to the NSArchiver. You see ounce I discovered these 
problems (possibly bugs, lake of documentation or whatever), I realized I 
needed a simple Bugg Application to demonstrate and simplify the problems. 
Unfortunately even in an Application this is kind of complicated, because on 
must have a proxy that can override the forwardInvocation: method etc. to 
achieve the most basic simulation. Well at least I have it down to one 
application but I still have three objects.
I further have run into more difficulties seemingly from within an application 
instead of the original objective tools.
Now first I would like to explain that within an application, and the 
forwardInvocation: method of a proxy, if one attempts to do this ...
 crashedArchiverData = [NSArchiver archivedDataWithRootObject:(id)anInvocation];
The program will crash terminated with signal 11 (SIGSEGV), a segment 
violation. (For seemingly no reason I can do anything about ! Any thoughts 
there?) In the Tool this works fine.

Finally if I try to do this like the tool which does invoke similar 
difficulties I do have to set the return value in the client via say this 
simple test without sending the invocation to a remote object (even though it's 
not actually invoked the problems are the same)...
- (void)forwardInvocation:(NSInvocation *)anInvocation {
 void *buffer = malloc(5);

 [anInvocation setReturnValue:[NSString stringWithString:@"Invocation Return 
Value"]];

 [anInvocation getReturnValue:(void *)buffer];
 NSLog([NSString stringWithFormat:@"The Value IS ... (%@)", *(id *)buffer]);
}
I get an result like this ...
SetValueInInvocation[5942] The Value IS ... (NSCFString)
... When I setStringValue with the return value, notice it's not the actual 
value of the String that was set there. Why? What's wrong is it me?

The strange thing is I have set it to an NSString but I get something bogus!! 
What's UP ??
Now I have tried everything under the 'Apple' possible and I really thing that 
it should work fine with the simplest form or this is designed poorly and not 
documented properly. Mostly they say "You should never have to do this 
yourself!", but of course we have to finish the job of making PDO work properly 
(or better) again and this is critical to a messaging language Objective-C and 
the need for Network savvy system in this modern connected world or it ain't 
worth anything (If I ever get OSX to a usable state it will have to be called a 
susstem, or have required another 10 months of bug reporting and maybe a couple 
of more year/versions for the stability and function OpenStep provided.)

Next I recall trying to us the passed arguments to return values. Even with 
retainArguments, etc. nothing seems to work. The Archiver in the tool complains 
if you send more then one argument, within the Archiving of an Invocation it 
complains that I do not understand what type an @@ idid is!? Clearly that has 
not been tested beyond a single argument, and is extremely buggy and unusable.
So I can imagine replacing the functionality of the Archiver by sending my own 
Object in the DataStream that can reproduce the return values in an invocation 
since that does not survive Unarchiving at all, but without the key to set the 
return value in a usable state. Then a call like ...
[NEWPDO_ReturnString setString:[sever takeStringAndReturnAString:[NSString 
stringWithFormat:@"Do this action for user#%d or something", nextUserInt]]];
ERROR MESSAGE: SetValueInInvocation[5942] *** +[NSCFString length]: selector 
not recognized without saying *** +[NSCFString length]: selector not 
recognized, as far as I can tell OSX remains unusable for me, please HELP. 

I can send you the Bugg Demo Application Source Code (for the 
SetValueInInvocation.app) if you request it, the other near replacement to PDO 
is a little less easy to send nor do I think it is required to demonstrate the 
problems, and any possible solutions to the finally problems with it that seem 
at this point to be more problems with Apple's version of the Foundation 
Classes required for implementing a replacement for PDO.

  From   OSX Developer
  email: osx-developer@www.com



------------------------------------------------------------
WWW.COM - Where the Web Begins! http://www.www.com



reply via email to

[Prev in Thread] Current Thread [Next in Thread]