swarm-support
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Message forwarding...


From: Scott Christley
Subject: Re: Message forwarding...
Date: Wed, 19 Feb 1997 15:15:15 -0800

At 03:17 PM 2/19/97 +0000, Barry McMullin wrote:
>At 21:25 14/02/97 -0500, Wojtek Kopczuk <address@hidden> wrote:
>>I haven't seen an answer to your question yet so here it is:
>>you can implement message forwarding in GNU ObjC. 
>>Having following method does a trick:
>>
>>-forward: (SEL) aSelector : (arglist_t) arguments {
>>  return [ obj performv: aSelector : arguments];
>>}
>>
>>where 'obj' is an object to which method should be forwarded.
>
>I tried it and it works.  It's not a very severe test because
>my forwarded messages all have trivial interfaces (at most an
>int argument, and an int return), but it does prove the principle.

Warning! Warning! Danger! Danger!  (Wave your arms around) :-)

Forwarding is great an wonderful but there are definitely problems depending
upon what version of the ObjC runtime that you have in your GCC.  The most
recent snapshot that I released back in 960906 still has a problem, so try
both of the programs to test; this only relates to i386 machines though as
far as I know.  

The first program tests the problem with initialization of the floating
point stack; the second has to do with return floats/doubles from forwarded
methods.

*** test-double.m: test program ***
*/

#include <objc/Object.h>

@interface TestDouble : Object
+ (double) testDouble;
- (double) testDoubleInstance;
@end

@implementation TestDouble
+ (double) testDouble
{
  return 123456789.0;
}
- (double) testDoubleInstance
{
  return 987654321.0;
}
@end

int main()
{
  double foo;
  id bar;
  
  foo = [TestDouble testDouble];
  printf ("TestDouble 1st call is %f\n", foo);

  foo = [TestDouble testDouble];
  printf ("TestDouble 2nd call is %f\n", foo);

  bar = [[TestDouble alloc] init];
  foo = [bar testDoubleInstance];
  printf ("testDouble is %f\n", foo);
}

/*
*** test-double.m: bad results  ***

TestDouble 1st call is NaN
TestDouble 2nd call is 123456789.000000
testDouble is 987654321.000000

*/


/*
  second program
  the results of both runs should be identical
*/

#include <stdio.h>
#include <objc/Object.h>

@protocol test1
- init;
@end
@protocol test2
- free;
@end;

typedef struct _EightInt {
        int     one;
        int     two;
        int     three;
        int     four;
        int     five;
        int     six;
        int     seven;
        int     eight;
        int     nine;
        int     ten;
        int     eleven;
        int     twelve;
        }TwelveInt;

@interface Dummy1:Object < test1, test2 >
{
}

- (float)anInt:(int)a timesInt:(int)b plusFloat:(float)f;
- (float)times3:(float)num;
- (int)times2:(int)num;
- (double)doubleTimes:(double)d1 :(double)d2;
- (float)floatTimes:(float)d1 :(float)d2;
- (float)float4:(float)f1 :(float)f2 :(float)f3 :(float)f4;
- (int)sumStructPtr:(TwelveInt *)aStruct;
- (TwelveInt)newStruct;
@end

@implementation Dummy1

// this was put in to test the debugger for valid values on break point
// for subroutine with float values
float twoFloatProduct(float a, float b)
{
        float result = 0;  // THis is a test
        result = a;
        result = result * b;
        return result;
}

- init
{
        return [super init];
}

- free
{
        return [super free];
}

- (float)anInt:(int)a timesInt:(int)b plusFloat:(float)f
{
        float fa = a;
        float fb = b;
        float ret;

        ret = (fa * fb) + f;
        return ret;
}

- (float)times3:(float)num
{
        return twoFloatProduct(3.0, num);
}

- (int)times2:(int)num
{
        return 2.0 * num;
}

- (double)doubleTimes:(double)d1 :(double)d2
{
  double m;
  m = d1 * d2;
  return m;
}

- (float)floatTimes:(float)d1 :(float)d2
{
        // these intermediate values are here to test the debugger
        // without optimization to see if executed lines in method help
        float result ;
        result = d1 * d2;
        return result;
}

- (float)float4:(float)f1 :(float)f2 :(float)f3 :(float)f4
{
        return f1 * f2 * f3 * f4;
}

- (int)sumStructPtr:(TwelveInt *)aStruct;
{
  return aStruct->one+aStruct->two+aStruct->three+aStruct->four+
    aStruct->five+aStruct->six+aStruct->seven+aStruct->eight+
    aStruct->nine+aStruct->ten+aStruct->eleven+aStruct->twelve;
}

- (TwelveInt)newStruct
{
  TwelveInt st;

  st.one = 1;
  st.two = 2;
  st.three = 3;
  st.four = 4;
  st.five = 5;
  st.six = 6;
  st.seven = 7;
  st.eight = 8;
  st.nine = 9;
  st.ten = 10;
  st.eleven = 11;
  st.twelve = 12;
  return st;
}

@end

@interface Dummy2:Object
{
    id friend;
}

- setFriend:anObject;

@end

@implementation Dummy2

- setFriend:anObject
{
        friend = anObject;
        return self;
}

- (retval_t)forward:(SEL)aSelector :(arglist_t)argFrame
{
  retval_t ret;

  fprintf(stdout,"attempting to forward: ");
    if ( [friend respondsTo:aSelector] )
      {
        ret = [friend performv:aSelector :argFrame];
        return ret;
      }
    [self doesNotRecognize:aSelector];
}


@end

int runTestUsing(id testObj)
{
        TwelveInt       stru, nst;
        double          tf;
        double          pf;
        int             td;

        tf = [testObj anInt:2 timesInt:3 plusFloat:4.3];
        fprintf(stdout,"[testObj anInt:2 timesInt:3 plusFloat:4.3] = %f\n",tf);
        tf = [testObj times3:9.0];
        fprintf(stdout,"[testObj times3:9] =%f\n", tf);
        td = [testObj times2:8];
        fprintf(stdout,"[testObj times2:8] =%d\n", td);
        pf = [testObj doubleTimes:20:4];
        fprintf(stdout,"[testObj doubleTimes:20:4] =%lf\n", pf);
        tf = [testObj floatTimes:20:4];
        fprintf(stdout,"[testObj floatTimes:20:4] =%f\n", tf);
        tf = [testObj float4:3.0 : 4.0 : 5.0 : 6.0];
        fprintf(stdout,"float4:%5.2f:%5.2f:%5.2f:%5.2f = %f\n", 3.0, 4.0,
                5.0, 6.0, tf);

        stru.one =      stru.two =      stru.three = 100;
        stru.four =     stru.five =     stru.six = 3;
        stru.seven =    stru.eight =    33 ;
        stru.nine = stru.ten = stru.eleven = stru.twelve = 5 ;
        td = [testObj sumStructPtr:&stru];
        fprintf(stdout,"Sum of stuct pointer passed in = %d\n", td);
        tf = [testObj times3: [testObj times3: 2]];
        fprintf(stdout,"[testObj times3:[testObj times3: 2]] = %f\n", tf);

        nst = [testObj newStruct];
        fprintf(stdout, "[testObj newStruct] %d %d %d %d %d %d %d %d %d %d %d 
%d\n",
                nst.one, nst.two, nst.three, nst.four, nst.five, nst.six,
                nst.seven, nst.eight, nst.nine, nst.ten, nst.eleven,
                nst.twelve);

        return 0;
}

int main (int argc, char *argv[])
{
        id      test1;
        id      test2;

        test1 = [[Dummy1 alloc] init];
        test2 = [[Dummy2 alloc] init];

        fprintf(stdout, "\n\nrunning tests\n");
        runTestUsing(test1);
        //
        //
        // test forwarding
        //
        //
        fprintf(stdout, "\n\nrunning tests using forwarding \n");
        [test2 setFriend:test1];
        runTestUsing(test2);

        exit(0);
}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]