Fix for fetching type information from remote system.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@17095 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2003-07-04 09:33:53 +00:00
parent 8831b90cc5
commit 2a99982e1a
8 changed files with 148 additions and 25 deletions

View file

@ -1,6 +1,13 @@
2003-07-04 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSDistantObject.m: Avoid recursion fetching method signature
* Source/NSDistantObject.m: Avoid recursion fetching method signature.
* Source/NSObject.m: ([methodSignatureForSelector:]) modified to take
into account any protocols that the receiver conforms to, so the
returned signature has the fullest possible type information.
* Source/GSFFCallInvocation.m: Fetch method signature from receiver
in preference to using other info. Ensures we have correct info for
the object we are sending the message to.
* Source/GSFFIInvocation.m: ditto
2003-07-03 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -768,20 +768,35 @@ GSInvocationCallback (void *callback_data, va_alist args)
@" to forwardInvocation: for '%s'",
object_get_class_name (obj), sel_get_name(selector));
}
selector = gs_find_by_receiver_best_typed_sel (obj, selector);
sig = nil;
if (sel_get_type (selector))
sig = [obj methodSignatureForSelector: selector];
/*
* If we got a method signature from the receiving object,
* ensure that the selector we are using matches the types.
*/
if (sig != nil)
{
const char *receiverTypes = [sig methodType];
const char *runtimeTypes = sel_get_type (selector);
if (runtimeTypes == 0 || strcmp(receiverTypes, runtimeTypes) != 0)
{
const char *runtimeName = sel_get_name (selector);
selector = sel_get_typed_uid (runtimeName, receiverTypes);
if (selector == 0)
{
selector = sel_register_typed_name (runtimeName, receiverTypes);
}
}
}
if (sig == nil && sel_get_type (selector) != 0)
{
sig = [NSMethodSignature signatureWithObjCTypes: sel_get_type(selector)];
}
if (!sig)
{
sig = [obj methodSignatureForSelector: selector];
}
NSCAssert1(sig, @"No signature for selector %@",
NSStringFromSelector(selector));

View file

@ -374,19 +374,34 @@ GSFFIInvocationCallback(ffi_cif *cif, void *retp, void **args, void *user)
object_get_class_name (obj), sel_get_name(selector));
}
selector = gs_find_by_receiver_best_typed_sel (obj, selector);
sig = nil;
sig = [obj methodSignatureForSelector: selector];
/*
* If we got a method signature from the receiving object,
* ensure that the selector we are using matches the types.
*/
if (sig != nil)
{
const char *receiverTypes = [sig methodType];
const char *runtimeTypes = sel_get_type (selector);
if (runtimeTypes == 0 || strcmp(receiverTypes, runtimeTypes) != 0)
{
const char *runtimeName = sel_get_name (selector);
selector = sel_get_typed_uid (runtimeName, receiverTypes);
if (selector == 0)
{
selector = sel_register_typed_name (runtimeName, receiverTypes);
}
}
}
if (sel_get_type (selector))
if (sig == nil && sel_get_type (selector) != 0)
{
sig = [NSMethodSignature signatureWithObjCTypes: sel_get_type(selector)];
}
if (!sig)
{
sig = [obj methodSignatureForSelector: selector];
}
NSCAssert1(sig, @"No signature for selector %@",
NSStringFromSelector(selector));

View file

@ -704,7 +704,7 @@ enum
}
/*
* We don't need to retain the oibject here - the connection
* We don't need to retain the object here - the connection
* will retain the proxies local object if necessary (and release it
* when all proxies referring to it have been released).
*/

View file

@ -1238,21 +1238,74 @@ static BOOL double_release_check_enabled = NO;
*/
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector
{
const char *types;
struct objc_method *mth;
const char *types;
struct objc_method *mth;
Class c;
if (aSelector == 0)
[NSException raise: NSInvalidArgumentException
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
mth = (GSObjCIsInstance(self)
? GSGetInstanceMethod(GSObjCClass(self), aSelector)
: GSGetClassMethod((Class)self, aSelector));
if (GSObjCIsInstance(self))
{
c = GSObjCClass(self);
mth = GSGetInstanceMethod(c, aSelector);
}
else
{
c = (Class)self;
mth = GSGetClassMethod((Class)self, aSelector);
}
if (mth == 0)
{
return nil;
return nil; // Method not implemented
}
types = mth->method_types;
/*
* If there are protocols that this class conforms to,
* the method may be listed in a protocol with more
* detailed type information than in the class itsself
* and we must therefore use the information from the
* protocol.
* This is because protocols also carry information
* used by the Distributed Objects system, which the
* runtime does not maintain in classes.
*/
if (c->protocols != 0)
{
struct objc_protocol_list *protocols = c->protocols;
BOOL found = NO;
while (found == NO && protocols != 0)
{
unsigned i = 0;
while (found == NO && i < protocols->count)
{
Protocol *p;
struct objc_method_description *pmth;
p = protocols->list[i++];
if (c == (Class)self)
{
pmth = [p descriptionForClassMethod: aSelector];
}
else
{
pmth = [p descriptionForInstanceMethod: aSelector];
}
if (pmth != 0)
{
types = pmth->types;
found = YES;
}
}
protocols = protocols->next;
}
}
if (types == 0)
{
return nil;

View file

@ -17,6 +17,14 @@
#include "wgetopt.h"
/*
* Dummy declaration with different bycopy/byref info from the one
* in the server ... we expect the info from the server to be used.
*/
@interface Dummy : NSObject
- (id) quietBycopy: (id byref)a;
@end
@interface Auth : NSObject
@end
@ -275,6 +283,7 @@ con_messages (id prx)
printf("Testing bycopy/byref:\n");
[prx sendBycopy: obj];
[prx quietBycopy: obj];
#ifdef _F_BYREF
[prx sendByref: obj];

View file

@ -8,6 +8,8 @@
#include <Foundation/NSProcessInfo.h>
#include <Foundation/NSAutoreleasePool.h>
#include <Foundation/NSException.h>
#define IN_SERVER 1
#include "server.h"
#include "wgetopt.h"
@ -357,6 +359,13 @@
return self;
}
- quietBycopy: (bycopy id)o
{
printf(" >> quiet bycopy class is %s\n", object_get_class_name (o));
fflush(stdout);
return self;
}
- sendBycopy: (bycopy id)o
{
printf(" >> bycopy class is %s\n", object_get_class_name (o));

View file

@ -75,10 +75,25 @@ struct myarray {
- (oneway void) exceptionTest3;
@end
#ifdef IN_SERVER
/*
* We don't want the client to know about some methods, so we can
* check that they work when it doesn't know them.
*/
@protocol privateServer
- quietBycopy: (bycopy id)o;
@end
@interface Server : NSObject <ServerProtocol,privateServer>
{
id the_array;
}
@end
#else
@interface Server : NSObject <ServerProtocol>
{
id the_array;
}
@end
#endif
#endif /* _server_h */