mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
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:
parent
bcd9e0d209
commit
9f7fa664d7
5 changed files with 140 additions and 17 deletions
|
@ -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.
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]; \
|
||||
|
|
Loading…
Reference in a new issue