[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
- PDO replacement attempts, or How to setReturnValue of an NSInvocation,
OSX Developer <=