Added some invocation support.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@16349 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2003-04-04 10:03:08 +00:00
parent bcd9e0d209
commit 9f7fa664d7
5 changed files with 140 additions and 17 deletions

View file

@ -1,3 +1,10 @@
2003-04-04 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSInvocation: Added NS_INVOCATION asnd NS_MESSAGE
* Source/NSInvocation.m: Support the two new macros.
* Testing/nsinvocation.m: Trivial tests added.
* Documentation/OpenStepCompliance.gsdoc: Updated.
2003-04-03 Adam Fedor <fedor@gnu.org>
* Documentation/OpenStepCompliance.gsdoc: New file.
@ -15,7 +22,7 @@
* Headers/gnustep/base/Foundation.h: Revert previous change
22003-04-02 Richard Frith-Macdonald <rfm@gnu.org>
2003-04-02 Richard Frith-Macdonald <rfm@gnu.org>
* Source/Additions/GSXML.m: ([-content]) fix to produce string
content of elements rather than just text nodes.

View file

@ -42,6 +42,7 @@
<item>NSDistantObject</item>
<item>NSEnumerator</item>
<item>NSException</item>
<item>NSInvocation</item>
<item>NSLock</item>
<item>NSMethodSignature</item>
<item>NSMutableArray</item>
@ -73,18 +74,11 @@
<item>All Functions</item>
</list>
<p>
The following classes do NOT conform to the OpenStep specification.
</p>
<list>
<item>NSInvocation. NS_MESSAGE and NS_INVOCATION not defined</item>
<item>NSObject.
+cancelPreviousPerformRequestsWithTarget:selector:object: missing.
</item>
</list>
<p>
The following OpenStep classes are not implemented. The usefulness
of these classes it marginal so it is likely that we will never
implement these classes.
implement these classes. However, we would be pleaqsed to accept
their contribution should anyone care to implement them and assign
the copyright to the Free Software Foundation.
</p>
<list>
<item>NSBTreeBlock</item>

View file

@ -96,5 +96,24 @@
@end
#endif
/* Do NOT use these methods ... internal use only ... not public API */
@interface NSInvocation (MacroSetup)
+ (id) _newProxyForInvocation: (id)target;
+ (id) _newProxyForMessage: (id)target;
+ (NSInvocation*) _returnInvocationAndDestroyProxy: (id)proxy;
@end
#define NS_INVOCATION(class, message...) ({\
id __proxy = [NSInvocation _newProxyForInvocation: class]; \
[__proxy message]; \
[NSInvocation _returnInvocationAndDestroyProxy: __proxy]; \
})
#define NS_MESSAGE(target, message...) ({\
id __proxy = [NSInvocation _newProxyForMessage: target]; \
[__proxy message]; \
[NSInvocation _returnInvocationAndDestroyProxy: __proxy]; \
})
#endif /* __NSInvocation_h_GNUSTEP_BASE_INCLUDE */

View file

@ -40,6 +40,20 @@
static Class NSInvocation_abstract_class;
static Class NSInvocation_concrete_class;
@interface GSInvocationProxy
{
@public
Class isa;
id target;
NSInvocation *invocation;
}
+ (id) _newWithTarget: (id)t;
- (NSInvocation*) _invocation;
- (void) forwardInvocation: (NSInvocation*)anInvocation;
@end
@interface GSMessageProxy : GSInvocationProxy
@end
@implementation NSInvocation
#ifdef USE_LIBFFI
@ -132,6 +146,11 @@ _arg_addr(NSInvocation *inv, int index)
}
}
/**
* Returns an invocation instance which can be used to send messages to
* a target object using the described signature.<br />
* Raises an NSInvalidArgumentException if the signature is nil.
*/
+ (NSInvocation*) invocationWithMethodSignature: (NSMethodSignature*)_signature
{
return AUTORELEASE([[NSInvocation_concrete_class alloc]
@ -197,10 +216,12 @@ _arg_addr(NSInvocation *inv, int index)
[super dealloc];
}
/*
* Accessing message elements.
/**
* Copies the argument identified by index into the memory location specified
* by the buffer argument.<br />
* An index of zero is the target object, an index of one is the selector,
* so the actual method arguments start at index 2.
*/
- (void) getArgument: (void*)buffer
atIndex: (int)index
{
@ -635,8 +656,10 @@ _arg_addr(NSInvocation *inv, int index)
return nil;
}
/*
* This is the de_signated initialiser.
/** <init /><override-subclass />
* Initialised an invocation instance which can be used to send messages to
* a target object using aSignature.<br />
* Raises an NSInvalidArgumentException if aSignature is nil.
*/
- (id) initWithMethodSignature: (NSMethodSignature*)aSignature
{
@ -644,6 +667,12 @@ _arg_addr(NSInvocation *inv, int index)
return nil;
}
/**
* Tries to produce a method signature based on aSelector and uses that to
* initialise self by calling the -initWithMethodSignature: method.<br />
* If the argument type of aSelector cannot be determined, this releases self
* and returns nil.
*/
- (id) initWithSelector: (SEL)aSelector
{
const char *types;
@ -784,6 +813,21 @@ _arg_addr(NSInvocation *inv, int index)
_sendToSuper = flag;
}
/* These next three are for internal use only ... not public API */
+ (id) _newProxyForInvocation: (id)target
{
return [GSInvocationProxy _newWithTarget: target];
}
+ (id) _newProxyForMessage: (id)target
{
return [GSMessageProxy _newWithTarget: target];
}
+ (NSInvocation*) _returnInvocationAndDestroyProxy: (id)proxy
{
NSInvocation *inv = [proxy _invocation];
NSDeallocateObject(proxy);
return inv;
}
@end
@implementation NSInvocation (BackwardCompatibility)
@ -846,3 +890,43 @@ _arg_addr(NSInvocation *inv, int index)
return mframe_handle_return(_info[0].type, _retval, argFrame);
}
@end
@implementation GSInvocationProxy
+ (id) _newWithTarget: (id)t
{
GSInvocationProxy *o;
o = (GSInvocationProxy*) NSAllocateObject(self, 0, NSDefaultMallocZone());
o->target = t;
return o;
}
- (NSInvocation*) _invocation
{
return invocation;
}
- (retval_t) forward: (SEL)aSel : (arglist_t)argFrame
{
NSInvocation *inv;
if (aSel == 0)
[NSException raise: NSInvalidArgumentException
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
inv = AUTORELEASE([[NSInvocation alloc] initWithArgframe: argFrame
selector: aSel]);
[self forwardInvocation: inv];
return [inv returnFrame: argFrame];
}
- (void) forwardInvocation: (NSInvocation*)anInvocation
{
invocation = anInvocation;
}
@end
@implementation GSMessageProxy
- (NSInvocation*) _invocation
{
[invocation setTarget: target];
return invocation;
}
@end

View file

@ -196,7 +196,7 @@ main ()
float f;
double d;
id o;
char* str;
char *str;
NSInvocation *inv;
NSMethodSignature *sig;
Target *t;
@ -209,6 +209,25 @@ printf("Starting\n");
printf("Calling proxy\n");
[p loopInt: 1];
printf("Testing NS_MESSAGE ... ");
inv = NS_MESSAGE(t, loopInt: 5);
[inv invoke];
[inv getReturnValue: &i];
if (i == 6)
printf("OK\n");
else
printf("ERROR ... expecting 6 and got %d\n", i);
printf("Testing NS_INVOCATION ... ");
inv = NS_MESSAGE([Target class], loopInt: 7);
[inv setTarget: t];
[inv invoke];
[inv getReturnValue: &i];
if (i == 8)
printf("OK\n");
else
printf("ERROR ... expecting 8 and got %d\n", i);
#define SETUP(X) \
sig = [t methodSignatureForSelector: @selector(X)]; \
inv = [NSInvocation invocationWithMethodSignature: sig]; \