본문 바로가기

IOS Dev

Cast of C pointer type 'void *' to Objective-C pointer type 어쩌고저쩌고 에러가 나는 경우

이전에는 이런 예러가 없었는데 이전 소스를 새 프로젝트에 넣다가 보면 이런 에러가 생기는 경우가 있다.


일단 cast 문제인데.. 당황스럽다.!!!


다음과같이해서 수정하였다..!!


결론은 캐스팅할때 __bridge 를 같이 넣자이다.!!!


All is fine and well with ARC in Objective-C land. However, as soon as you also work with C or C++ code — such as the Chipmunk or Box2D libraries, or the Core Foundation framework — you may find yourself facing compiler errors.

Fortunately, it's half as bad if you understand why the compiler keeps bugging you.

Errors you'll see when casting id to void* and vice versa

Most errors when working with C/C++ code has to do with the fact that you can't freely cast id to void* and vice versa. For example, the below example won't work:

NSObject* myObject = [[NSObject alloc] init];
void* myObjectPointer = myObject; // ERROR
 
void* myObjectPointer2 = NULL;
NSObject* myObject2 = myObjectPointer2; // ERROR

You'll get an error like this one:
error: cannot initialize a variable of type '...' with an lvalue of type '...'

The types in the error message mentioned may differ but you'll see a __strong keyword thrown in for good measure. Well, you might think this can be fixed by properly casting to the correct types:

NSObject* myObject = [[NSObject alloc] init];
void* myObjectPointer = (void*)myObject; // ERROR, still ...
     
void* myObjectPointer2 = NULL;
NSObject* myObject2 = (NSObject*)myObjectPointer2; // ERROR, still ...

This time the error is different, each of the two casts above generates a different message:

1: Cast of Objective-C pointer type 'NSObject *' to C pointer type 'void *' requires a bridged cast
2: Cast of C pointer type 'void *' to Objective-C pointer type 'NSObject *' requires a bridged cast

What is a "bridged cast"?

ARC adds the keywords __bridge__bridge_transfer and __bridge_retained which must be used when casting. Here's the above example with a "bridged cast" that fixes the compile errors:

NSObject* myObject = [[NSObject alloc] init];
void* myObjectPointer = (__bridge void*)myObject;
     
void* myObjectPointer2 = NULL;
NSObject* myObject2 = (__bridge NSObject*)myObjectPointer2;

The use of __bridge in the cast tells the compiler that the object's lifetime doesn't change, and that you understand that if the object's memory is released it may result in a dangling pointer and a potential crash. This is the same behavior to non-ARC code, but ARC really wants to make sure you understand the implications and potential dangers. In ARC terms, you specify that the cast creates a "unsafe unretained" reference.

Bridge casts for Core Foundation

When interfacing with Core Foundation you may want to use __bridge_retain to tell ARC to take on ownership of the object (retain it). Likewise, __bridge_transfer tells ARC to release the object after the expression.

More about bridge casts

For more details about bridged casts read the section about Bridged Casts and the follow-up section Conversion of retainable object pointers in the LLVM compiler documentation.

Box2D & Chipmunk real-world examples
CCSprite* aSprite = [CCSprite spriteWithFile:@"image.png"];
 
 
// Assigning sprite to Box2D userdata
b2BodyDef bodyDef;
bodyDef.userData = (__bridge void*)aSprite;
 
// Getting the userdata sprite from Box2D
CCSprite* sprite = (__bridge CCSprite*)body->GetUserData();
 
 
// Assigning sprite to Chipmunk userdata
cpShape* shape = cpPolyShapeNew(staticBody, numVertices, vertices, offset);
shape->data = (__bridge void*)aSprite;
 
// Getting the userdata sprite from Chipmunk
CCSprite* sprite = (__bridge CCSprite*)shape->data;


[원문] http://www.kobold2d.com/pages/viewpage.action?pageId=919981 

'IOS Dev' 카테고리의 다른 글

IOS Opencv  (0) 2012.08.22
아이폰에서 Face Detection 하기  (1) 2012.08.22
Introduction to MapKit on iOS Tutorial  (0) 2012.08.17
괜찮은 IOS 개발 블로그- 기본 공부  (0) 2012.08.17