Use NSValue to wrap a C pointer

1.3k views Asked by At

I have a C type pointer variable:

a_c_type *cTypePointer = [self getCTypeValue];

How can I convert cTypePointer to NSObject type & vise versa?

Should I use NSValue? What is the proper way to do so with NSValue?

2

There are 2 answers

3
Florian Burel On BEST ANSWER

You can indeed use a NSValue.

a_c_type *cTypePointer = [self getCTypeValue];
NSValue * storableunit = [NSValue valueWithBytes:cTypePointer objCType:@encode(a_c_type)];

note that the 1st parameter is a pointer (void*). the object will contain the pointed value.

to get back to C:

a_c_type element;
[value getValue:&element];

Note that you would get the actual value, not the pointer. But then, you can just

 a_c_type *cTypePointer = &element

Test it :

- (void) testCVal
{
    double save = 5.2;
    NSValue * storageObjC = [NSValue valueWithBytes:&save objCType:@encode(double)];


    double restore;
    [storageObjC getValue:&restore];

    XCTAssert(restore == save, @"restore should be equal to the saved value");

}

test with ptr :

typedef struct
{
    NSInteger day;
    NSInteger month;
    NSInteger year;
} CDate;

- (void) testCVal
{
    CDate save = (CDate){8, 10, 2016};
    CDate* savePtr = &save;

    NSValue * storageObjC = [NSValue valueWithBytes:savePtr objCType:@encode(CDate)];


    CDate restore;
    [storageObjC getValue:&restore];
    CDate* restorePtr = &restore;

    XCTAssert(restorePtr->day == savePtr->day && restorePtr->month == savePtr->month && restorePtr->year == savePtr->year, @"restore should be equal to the saved value");

}
0
CRD On

You simply use the method valueWithPointer: to wrap a pointer value as an NSValue object, and pointerValue to extract the pointer value.

These are just like valueWithInt:/intValue et al - they wrap the primitive value. You are not wrapping what the pointer points at. Therefore it is important that you ensure that when extract the pointer that whatever it pointed at is still around, or else the pointer value will be invalid.

Finally you must cast the extract pointer value, which is returned as a void *, back to be its original type, e.g. a_c_type * in your example.

(If you want to wrap what is being pointed at consider NSData.)

HTH