views:

40

answers:

1

I'm experimenting with Obj-C blocks and trying to have a struct with two blocks in it where one block is to change what the other block does.

this is a really roundabout way to do something simple... and there may be better ways to do it, but the point of the exercise is for me to understand blocks. here's the code , it doesn't work, so what am I missing/not understanding and/or doing wrong?

//enumerate my math operation options so i can have something more understandable
//than 0, 1, 2, etc... also makes it easier to add operations, as opTypeTotal
//will be 1 plus the index of the operation before it.
typedef enum
{
 opTypeAdd = 0,
 opTypeSubtract = 1,
 opTypeTotal
} opType; 

//not sure if (struct someMathStruct)* is correct, probably is wrong
//the intent is to pass a pointer to someMathStruct, but the compiler
//won't know about its existance until a few lines later...
typedef (void)(^changeBlock)(opType,(struct someMathStruct)*);
typedef (void)(^mathBlock)(int,int,int*);

//hold two blocks, to be defined later at runtime
typedef struct someMathStruct{
 mathBlock doMath;
 changeBlock changeOperation;
} SomeMath;

//i want to declare an array of blocks of type mathBlock
//the intent is to have the array index to correspond with the opTypes enumerated above
//almost certain i'm doing this wrong
mathBlock *m[opTypeTotal] = malloc(sizeof(mathBlock *)*opTypeTotal);

//just two simple math operations as blocks
m[opTypeAdd] = ^(void)(int a,int b,int *result){*result = a+b;};
m[opTypeSubtract] = ^(void)(int a,int b,int *result){*result = a-b;};

//this block is what's supposed to change the other block in the struct
//it takes an opType, and a pointer to the SomeMath struct
//is this the right way to access the member variables of the struct?
changeBlock changeMe = ^(void)(opType a, SomeMath *b) {
  //should make adding operations as easy as just adding cases
 switch (a)
 {
  case opTypeAdd: *b.doMath=m[a]; break;
  case opTypeSubtract:
  default:  *b.doMath=m[a];  //catch-all goes to subtracting
 }
}

...

SomeMath mathFun;
int theTotal = 0;  //a test int to work with

//do i need to copy the changeMe block?
//or can i just do what i'm doing here as the block itself isn't unique
mathFun.changeOperation = changeMe;

mathFun->changeOperation(opTypeAdd, &mathFun);
mathFun->doMath(theTotal,11,&theTotal); //result should be 11

mathFun->changeOperation(opTypeSubtract, &mathFun);
mathFun->doMath(theTotal,3,&theTotal); //result should be 8

NSLog(@"the result: %d",theTotal); //should output "the result: 8"
+1  A: 

The code seems to work as you expect (the result is 8) once you fix the compilation errors:

Compile with: gcc -o test test.m -framework Foundation

#import <Foundation/Foundation.h>

//enumerate my math operation options so i can have something more understandable
//than 0, 1, 2, etc... also makes it easier to add operations, as opTypeTotal
//will be 1 plus the index of the operation before it.
typedef enum
{
 opTypeAdd = 0,
 opTypeSubtract = 1,
 opTypeTotal
} opType; 

struct someMathStruct; // Forward declare this as a type so we can use it in the 
                       // changeBlock typedef

typedef void (^changeBlock) (opType,struct someMathStruct*);
typedef void (^mathBlock) (int,int,int*);

//hold two blocks, to be defined later at runtime
typedef struct someMathStruct{
 mathBlock doMath;
 changeBlock changeOperation;
} SomeMath;


int main()
{

    //i want to declare an array of blocks of type mathBlock
    //the intent is to have the array index to correspond with the opTypes
    // enumerated above
    mathBlock *m = calloc(opTypeTotal, sizeof(mathBlock *));

    //just two simple math operations as blocks
    m[opTypeAdd] = ^(int a,int b,int *result){*result = a+b;};
    m[opTypeSubtract] = ^(int a,int b,int *result){*result = a-b;};

    changeBlock changeMe = ^(opType a, SomeMath *b) {
      //should make adding operations as easy as just adding cases
     switch (a)
     {
      case opTypeAdd: b->doMath = m[a]; break;
      case opTypeSubtract:
      default:  b->doMath = m[a];  //catch-all goes to subtracting
     }
    };

    SomeMath mathFun;
    int theTotal = 0;  //a test int to work with

    mathFun.changeOperation = changeMe;

    mathFun.changeOperation(opTypeAdd, &mathFun);
    mathFun.doMath(theTotal,11,&theTotal); //result should be 11

    mathFun.changeOperation(opTypeSubtract, &mathFun);
    mathFun.doMath(theTotal,3,&theTotal); //result should be 8

    NSLog(@"the result: %d",theTotal); //should output "the result: 8"
}
nall
awesome! the forward declaration was one thing i missed. as well as the syntax for the blocks. and also missed the calloc for the array. literally beating my head over this. thanks!
pxl