Question

I'm implementing a objective C wrapper for Box2d (which is written in c++). The b2Body keeps a reference to its wrapper B2Body in its userData field. GetUserData returns a void*. I'm now implementing fast iteration for getting the B2Bodies out of the B2World.

I get an 'Assigning to 'id' from incompatible type 'B2Body *' error at the line indicated below. Why?

#import "B2Body.h"
#import "B2World.h"
#import "Box2d.h"

@implementation B2World

-(id) initWithGravity:(struct B2Vec2) g
{
  if (self = [super init])
  {
    b2Vec2 *gPrim = (b2Vec2*)&g;
    _world = new b2World(*gPrim);
  }

  return self;
}

- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len;

{
  if(state->state == 0)
  {
    state->mutationsPtr = (unsigned long *)self;
    state->extra[0] = (long) ((b2World*)_world)->GetBodyList();
    state->state = 1;
  }

  // pull the box2d body out of extra[0]
  b2Body *b = (b2Body*)state->extra[0];

  // if it's nil then we're done enumerating, return 0 to end
  if(b == nil)
  {
    return nil;
  }

  // otherwise, point itemsPtr at the node's value
  state->itemsPtr = ((B2Body*)b->GetUserData()); // ERROR
  state->extra[0] = (long)b->GetNext();

  // we're returning exactly one item
  return 1;
}

`

B2Body.h looks like this: #import

@interface B2Body : NSObject
{
  int f;
}

-(id) init;
@end
Was it helpful?

Solution

NSFastEnumerationState is a C structure, and the itemsPtr field is:

id __unsafe_unretained  *itemsPtr;

In earlier versions, the __unsafe_unretained specifier was obviously missing.

Note, that the field itemsPtr is a pointer-to-id. Since id is essentially a pointer, itemsPtr is a pointer to an object pointer. Actually, this field is what holds the array of objects that allows the fast enumeration. Basically, it trolls through this array of object pointers.

Since I know nothing about Box2d, that's about all I can say. Assuming b->GetUserData() returns a pointer to an array of objects, you should be able to do this:

state->itemsPtr = (__unsafe_unretained id *)b->GetUserData();

While a bit dated, Mike Ash's article is still a great source for implementing fast enumeration.

EDIT

Just noticed that you are returning a single object. So, I assume GetUserData just returns a single object pointer. Since you need to return a pointer to object pointers, you would need to do something like this:

id object = (__bridge id)b->GetUserData();
state->itemsPtr = &object;

However, that stack object will be gone once you return from this method, which is why you are passed a stack buffer you can use. Thus, you should probably stuff that single pointer into the provided stack buffer:

*buffer = (__bridge id)b->GetUserData()
state->itemsPtr = buffer;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top