Passing a CFStringRef pointer to a C function in MacRuby
문제
I wanted to call the following function from OS X's DVDPlayback framework:
OSStatus DVDGetMediaVolumeCFName (
CFStringRef *outDiscVolumeCFName
);
Eventually, I came up with the following working code:
framework 'DVDPlayback'
p2 = Pointer.new_with_type('^{__CFString}')
DVDGetMediaVolumeCFName(p2)
But I didn't find the '^{__CFString}'
bit in any documentation and only found out what it was really doing afterward (I originally cut and pasted it from an error message). I first tried Pointer.new with both :id and :string with no success.
So my questions are:
- what's the best way to get this pointer (my way seems ugly)?
- why didn't Pointer.new(:string) work? I thought String, NSString, and CFString were equivalent
- where would I have looked to find this info? (I checked the MacRuby site, "macro Pointer" reported "Nothing known about Pointer", ~12 google hits, and "MacRuby: The Definitive Guide")
해결책
Although there exists a "toll-free" bridge from NSString to CFStringRef, the same does not apply for NSString* to CFStringRef*, due to the use of ARC (Automatic Reference Counting). Casting a CFStringRef* to NSString* requires the use of __bridge, therefore
Pointer.new(:string)
will not work. Using
Pointer.new_with_type('^{__CFString}')
is the best way get this pointer and the best way to find this information is to view the TypeError that is generated when the incorrect type is chosen. For example:
expected instance of Pointer of type `^{__CFString}', got `*' (TypeError)