#include #include #include #include #include typedef struct { char c; int i; } small; typedef struct { int i; char *s; float f; } large; @interface Target: NSObject - (char) loopChar: (char)v; - (double) loopDouble: (double)v; - (float) loopFloat: (float)v; - (int) loopInt: (int)v; - (large) loopLarge: (large)v; - (long) loopLong: (long)v; - (large) loopLargePtr: (large*)v; - (id) loopObject: (id)v; - (short) loopShort: (short)v; - (small) loopSmall: (small)v; - (small) loopSmallPtr: (small*)v; - (char*) loopString: (char*)v; - (char) retChar; - (double) retDouble; - (float) retFloat; - (int) retInt; - (large) retLarge; - (long) retLong; - (id) retObject; - (short) retShort; - (small) retSmall; - (char*) retString; @end @implementation Target - (char) loopChar: (char)v { return v+1; } - (double) loopDouble: (double)v { return v+1.0; } - (float) loopFloat: (float)v { return v+1.0; } - (int) loopInt: (int)v { return v+1; } - (large) loopLarge: (large)v { return v; } - (long) loopLong: (long)v { return v+1; } - (large) loopLargePtr: (large*)v { return *v; } - (id) loopObject: (id)v { return v; } - (short) loopShort: (short)v { return v+1; } - (small) loopSmall: (small)v { return v; } - (small) loopSmallPtr: (small*)v { return *v; } - (char*) loopString: (char*)v { return v; } - (char) retChar { return (char)99; } - (double) retDouble { return 123.456; } - (float) retFloat { return 123.456; } - (int) retInt { return 123456; } - (large) retLarge { static large l = { 99, "large", 99.99 }; return l; } - (long) retLong { return 123456; } - (id) retObject { return self; } - (short) retShort { return 12345; } - (small) retSmall { static small s = { 11, 22 }; return s; } - (char*) retString { return "string"; } @end @interface MyProxy : NSObject { id obj; } - (void) forwardInvocation: (NSInvocation*)inv; - (id) initWithTarget: (id)target; @end @implementation MyProxy - (id) initWithTarget: (id)target { obj = target; return self; } - (void) forwardInvocation: (NSInvocation*)inv { NSData *d = [NSArchiver archivedDataWithRootObject: inv]; NSInvocation *i = [NSUnarchiver unarchiveObjectWithData: d]; unsigned l; void *b; [i invokeWithTarget: obj]; d = [NSArchiver archivedDataWithRootObject: i]; i = [NSUnarchiver unarchiveObjectWithData: d]; l = [[i methodSignature] methodReturnLength]; b = (void *)objc_malloc(l); [i getReturnValue: b]; [inv setReturnValue: b]; objc_free(b); } @end int main () { large la; small sm; large tmpla; large *laptr = &tmpla; small tmpsm; small *smptr = &tmpsm; int i; char c; short s; long l; float f; double d; id o; char* str; NSInvocation *inv; NSMethodSignature *sig; Target *t; id p; NSAutoreleasePool *arp = [NSAutoreleasePool new]; t = [Target new]; p = [[MyProxy alloc] initWithTarget: t]; #define SETUP(X) \ sig = [t methodSignatureForSelector: @selector(X)]; \ inv = [NSInvocation invocationWithMethodSignature: sig]; \ [inv setSelector: @selector(X)]; tmpsm.c = 8; tmpsm.i = 9; tmpla.i = 1; tmpla.s = "hello"; tmpla.f = 1.23; SETUP(retChar); [inv invokeWithTarget: t]; printf("Expect: 99, "); [inv getReturnValue: &c]; printf("invoke: %d ", c); c = [p retChar]; printf("forward: %d\n", c); SETUP(retShort); [inv invokeWithTarget: t]; printf("Expect: 12345, "); [inv getReturnValue: &s]; printf("invoke: %d ", s); s = [p retShort]; printf("forward: %d\n", s); SETUP(retInt); [inv invokeWithTarget: t]; printf("Expect: 123456, "); [inv getReturnValue: &i]; printf("invoke: %d ", i); i = [p retInt]; printf("forward: %d\n", i); SETUP(retLong); [inv invokeWithTarget: t]; printf("Expect: 123456, "); [inv getReturnValue: &l]; printf("invoke: %ld ", l); l = [p retLong]; printf("forward: %ld\n", l); SETUP(retFloat); [inv invokeWithTarget: t]; printf("Expect: 123.456, "); [inv getReturnValue: &f]; printf("invoke: %.3f ", f); f = [p retFloat]; printf("forward: %.3f\n", f); SETUP(retDouble); [inv invokeWithTarget: t]; printf("Expect: 123.456, "); [inv getReturnValue: &d]; printf("invoke: %.3f ", d); d = [p retDouble]; printf("forward: %.3f\n", d); SETUP(retObject); [inv invokeWithTarget: t]; printf("Expect: %x, ", t); [inv getReturnValue: &o]; printf("invoke: %x ", o); o = [p retObject]; printf("forward: %x\n", o); SETUP(retString); [inv invokeWithTarget: t]; printf("Expect: 'string', "); [inv getReturnValue: &str]; printf("invoke: '%s' ", str); str = [p retString]; printf("forward: '%s'\n", str); SETUP(retSmall); [inv invokeWithTarget: t]; printf("Expect: {11,22}, "); [inv getReturnValue: &sm]; printf("invoke: {%d,%d} ", sm.c, sm.i); sm = [p retSmall]; printf("forward: {%d,%d}\n", sm.c, sm.i); SETUP(retLarge); [inv invokeWithTarget: t]; printf("Expect: {99,large,99.99}, "); [inv getReturnValue: &la]; printf("invoke: {%d,%s,%.2f} ", la.i, la.s, la.f); la = [p retLarge]; printf("forward: {%d,%s,%.2f}\n", la.i, la.s, la.f); SETUP(loopChar:); c = 0; [inv setArgument: &c atIndex: 2]; [inv invokeWithTarget: t]; printf("Expect: 1, "); [inv getReturnValue: &c]; printf("invoke: %d ", c); c = [p loopChar: 0]; printf("forward: %d\n", c); SETUP(loopShort:); s = 1; [inv setArgument: &s atIndex: 2]; [inv invokeWithTarget: t]; printf("Expect: 2, "); [inv getReturnValue: &s]; printf("invoke: %d ", s); s = [p loopShort: 1]; printf("forward: %d\n", s); SETUP(loopInt:); i = 2; [inv setArgument: &i atIndex: 2]; [inv invokeWithTarget: t]; printf("Expect: 3, "); [inv getReturnValue: &i]; printf("invoke: %d ", i); i = [p loopInt: 2]; printf("forward: %d\n", i); SETUP(loopLong:); l = 3; [inv setArgument: &l atIndex: 2]; [inv invokeWithTarget: t]; printf("Expect: 4, "); [inv getReturnValue: &l]; printf("invoke: %d ", l); l = [p loopLong: 3]; printf("forward: %d\n", l); SETUP(loopFloat:); f = 4.0; [inv setArgument: &f atIndex: 2]; [inv invokeWithTarget: t]; printf("Expect: 5.0, "); [inv getReturnValue: &f]; printf("invoke: %.1f ", f); f = [p loopFloat: 4.0]; printf("forward: %.1f\n", f); SETUP(loopDouble:); d = 5.0; [inv setArgument: &d atIndex: 2]; [inv invokeWithTarget: t]; printf("Expect: 6.0, "); [inv getReturnValue: &d]; printf("invoke: %.1f ", d); d = [p loopDouble: 5.0]; printf("forward: %.1f\n", d); SETUP(loopObject:); [inv setArgument: &p atIndex: 2]; [inv invokeWithTarget: t]; printf("Expect: %x, ", p); [inv getReturnValue: &o]; printf("invoke: %x ", o); o = [p loopObject: p]; printf("forward: %x\n", o); SETUP(loopString:); str = "Hello"; [inv setArgument: &str atIndex: 2]; [inv invokeWithTarget: t]; printf("Expect: 'Hello', "); [inv getReturnValue: &str]; printf("invoke: '%s' ", str); str = [p loopString: str]; printf("forward: '%s'\n", str); SETUP(loopSmall:); printf("Expect: {8,9}, "); [inv setArgument: &tmpsm atIndex: 2]; [inv invokeWithTarget: t]; [inv getReturnValue: &sm]; printf("invoke: {%d,%d} ", sm.c, sm.i); sm = [p loopSmall: tmpsm]; printf("forward: {%d,%d}\n", sm.c, sm.i); SETUP(loopLarge:); printf("Expect: {1,hello,1.23}, "); [inv setArgument: &tmpla atIndex: 2]; [inv invokeWithTarget: t]; [inv getReturnValue: &la]; printf("invoke: {%d,%s,%.2f} ", la.i, la.s, la.f); la = [p loopLarge: tmpla]; printf("forward: {%d,%s,%.2f}\n", la.i, la.s, la.f); SETUP(loopSmallPtr:); printf("Expect: {8,9}, "); [inv setArgument: &smptr atIndex: 2]; [inv invokeWithTarget: t]; [inv getReturnValue: &sm]; printf("invoke: {%d,%d} ", sm.c, sm.i); sm = [p loopSmallPtr: smptr]; printf("forward: {%d,%d}\n", sm.c, sm.i); SETUP(loopLargePtr:); printf("Expect: {1,hello,1.23}, "); [inv setArgument: &laptr atIndex: 2]; [inv invokeWithTarget: t]; [inv getReturnValue: &la]; printf("invoke: {%d,%s,%.2f} ", la.i, la.s, la.f); la = [p loopLargePtr: laptr]; printf("forward: {%d,%s,%.2f}\n", la.i, la.s, la.f); [arp release]; return 0; }