Incompatible types casting 'NSString *' to 'CTStringRef *' - objective-c

I'm just trying to cast NSString* to CTStringRef*
NSString *foobar = #"foobar";
CFStringRef *tmp = (__bridge_retained CFStringRef*)foobar;
Can someone help with this error?
"Incompatible types casting 'NSString *' to 'CTStringRef *' (aka const struct __CFString **)with a __bridge_retained cast"
I've tried with simply __bridge and it don't work either. From the documentation, I think the _retained is the right type I need.
Thanks.

If you look closely at the error message you will see what your problem is. The hint is in this part -
__CFString **
Notice the two * - This means that you are trying to cast to a pointer to a pointer, or in other words a reference to a reference. CTStringRef is already a reference, as implied by the 'Ref' part of the name, so you don't need the * in (__bridge_retained CFStringRef*)
Your code should read
NSString *foobar = #"foobar";
CFStringRef tmp = (__bridge_retained CFStringRef)foobar;

Related

How to do objective c style assignments after renaming file to .mm

This code compiles in a .m file, but not in an .mm file:
CFDataRef nativeSocket = CFWriteStreamCopyProperty((CFWriteStreamRef)outputStream, kCFStreamPropertySocketNativeHandle);
CFSocketNativeHandle *sock = (CFSocketNativeHandle *)CFDataGetBytePtr(nativeSocket);
The error message is:
Cannot initialize a variable of type 'CFDataRef' (aka 'const __CFData *') with an rvalue of type 'CFTypeRef' (aka 'const void *')
If I change the type of nativeSocket to CFTypeRef the error message becomes:
Candidate function not viable: cannot convert argument of incomplete type 'CFTypeRef' (aka 'const void *') to 'CFDataRef' (aka 'const __CFData *')
Please tell me how to fix this. I can't seem to guess what to google.
Thanks!
You just need to cast the result from CFWriteStreamCopyProperty() to the proper type:
CFDataRef nativeSocket = (CFDataRef)CFWriteStreamCopyProperty((CFWriteStreamRef)outputStream, kCFStreamPropertySocketNativeHandle);
CFSocketNativeHandle *sock = (CFSocketNativeHandle *)CFDataGetBytePtr(nativeSocket);
It's probably safer to extract the native handle this way, though:
CFSocketNativeHandle sock;
CFDataGetBytes(nativeSocket, CFRangeMake(0, sizeof(sock)), (UInt8*)&sock);
That avoids any issue with the data object's byte pointer being misaligned. Also, it ensures that you don't try to deference the byte pointer implicitly (by doing *sock) after the data object has been released.

Convert NSArray to CFStringRef *

I need a way to convert an NSArray to a null terminated list compatible with the arguments option of DADiskMountWithArguments.
The documentation specifies the argument option to be a "Null terminated list" of type CFStringRef arguments[].
I have created a Mount method that I want to pass an NSArray with the arguments, and in my method I need to convert the NSArray to a CFStringRef *.
I've tried myself but I always get in trouble with ARC, and I have not been able to find any good way to do this yet.
I've looked at the project Disk-Arbitrator in GitHub https://github.com/aburgh/Disk-Arbitrator/blob/master/Source/Disk.m for inspiration, and the creator of that application uses this method:
- (void)mountAtPath:(NSString *)path withArguments:(NSArray *)args
{
NSAssert(self.isMountable, #"Disk isn't mountable.");
NSAssert(self.isMounted == NO, #"Disk is already mounted.");
self.isMounting = YES;
Log(LOG_DEBUG, #"%s mount %# at mountpoint: %# arguments: %#", __func__, BSDName, path, args.description);
// ensure arg list is NULL terminated
id *argv = calloc(args.count + 1, sizeof(id));
[args getObjects:argv range:NSMakeRange(0, args.count)];
NSURL *url = path ? [NSURL fileURLWithPath:path.stringByExpandingTildeInPath] : NULL;
DADiskMountWithArguments((DADiskRef) disk, (CFURLRef) url, kDADiskMountOptionDefault,
DiskMountCallback, self, (CFStringRef *)argv);
free(argv);
}
But that is not allowed in ARC, and I can't find a way to do it.
Update for better clarity:
This line:
id *argv = calloc(args.count + 1, sizeof(id));
Gives the following error message:
Implicit conversion of a non-Objective-C pointer type 'void *' to
'__strong id *' is disallowed with ARC
Pointer to non-const type 'id' with no explicit ownership.
To fix that i try to do this:
id argv = (__bridge id)(calloc(args.count + 1, sizeof(id)));
Then this line:
[args getObjects:argv range:NSMakeRange(0, args.count)];
Gives the following errors:
[ERROR] Implicit conversion of an Objective-C pointer to
'__unsafe_unretained id *' is disallowed with ARC
[WARN] Incompatible pointer types sending '__string id' to parameter
of type '__unsafe_unretained id *'
The declaration of -getObjects:range: look like this:
- (void)getObjects:(id [])aBuffer range:(NSRange)aRange
So from the error message i got I assume i have to pass an '__unsafe_unretained id *' to 'getObjects:(id [])aBuffer'. So to fix that i declare my id as __unsafe_unretained like this:
__unsafe_unretained id argv = (__bridge __unsafe_unretained id)(calloc(args.count + 1, sizeof(id)));
And update this line like this:
[args getObjects:&argv range:NSMakeRange(0, args.count)];
Now i don't have any errors there, but in the call to DADiskMountWithArguments i get the following error:
Cast of an Objective-C pointer to 'CFStringRef *' (aka 'const struct
__CFString **) is disallowed with ARC
So here I got stuck as I have not been able to fix this error, and I don't know if I made mistakes earlier or if I haven't found the right way send the CFStringRef, therefore I decided to ask for guidance here.
This is how it looks in context, where args is an NSArray declared earlier:
__unsafe_unretained id argv = (__bridge __unsafe_unretained id)(calloc(args.count + 1, sizeof(id)));
[args getObjects:&argv range:NSMakeRange(0, args.count)];
DADiskMountWithArguments((DADiskRef) disk, (__bridge CFURLRef) url, kDADiskMountOptionDefault, NULL, (__bridge void *)self, (CFStringRef *)argv );
So my question is either, how can this method be made ARC-friendly, or is there another/better way to get from an NSArray to a NULL-terminated CFStringRef *
Try this:
CFStringRef *argv = calloc(args.count + 1, sizeof(CFStringRef));
CFArrayGetValues((__bridge CFArrayRef)args, CFRangeMake(0, args.count), (const void **)argv );
DADiskMountWithArguments((DADiskRef) disk, (CFURLRef) url, kDADiskMountOptionDefault,
DiskMountCallback, self, argv);
free(argv);
There are no Core Foundation/Cocoa memory management issues because CFArrayGetValues() doesn't give you ownership of the returned values.

Transform CBPeripheral's UUID to string format :

I am trying to transform a CBPeripheral's UUID to string format:
CBPeripheral* peripheral;
NSString *pUuid = (__bridge NSString *)(CFUUIDCreateString(nil, peripheral.UUID));
but i got this error:
Incompatible pointer types passing retainable parameter of type 'NSString *' to a CF functions expecting 'CFUUIDRef' (aka 'const struct _CFUUID *') type
peripheral.UUID is deprecated as of OSX 10.9 per the Apple Documents
To accomplish what you are trying to do, you use:
[peripheral.identifier UUIDString]

Casting an (NSString *) to (int *)?

I have an NSString.
NSString *str;
And I need to store it in a struct.
struct {
int *s;
} st;
And set it.
st.s = str;
So, how should I go about retrieving it?
return (__bridge_retained NSString *)st.s;
I've tried the above, and it gives the error: Incompatible types casting 'int *' to 'NSString *' with a __bridge_retained cast.
Answered the question. Simply define the NSString in the struct like this.
struct {
__unsafe_unretained NSString *s;
} st;
Thanks, Carl Veazey!
To store an Objective-C object in an struct you have a couple of options, the one I see most is to store it in the struct as __unsafe_unretained and then maintain a strong reference to it elsewhere.
From the "Common Issues While Converting a Project" section of the ARC Transition Notes:
If using Objective-C objects is sub-optimal, (maybe you want a dense
array of these structs) then consider using a void* instead. This
requires the use of the explicit casts...
They seem to imply __bridge is the way to cast void * to id but are not 100% clear on this.
The other option, which makes more sense to me personally and I've seen more often I think:
Mark the object reference as __unsafe_unretained. ... You declare the
structure as: struct x { NSString * __unsafe_unretained S; int X; }
Hope this helps!

warning: Semantic Issue: Incompatible pointer types initializing 'char *' with an expression of type 'NSString *'

I am trying to do the following:
NSString *personDesc = [NSString stringWithFormat:#"Person named %#", person.name];
char *myArguments[] = { personDesc, NULL };
But it is producing this error:
warning: Semantic Issue: Incompatible pointer types initializing 'char *' with an expression of type 'NSString *'
The reason I am trying to convert the NSString into a char is because I am passing myArguments into AuthorizationExecuteWithPrivileges
e.g.
AuthorizationExecuteWithPrivileges(auth, tool, kAuthorizationFlagDefaults, myArguments, NULL);
Any ideas?
As matt said above, you need to convert the NSString to a char* before you can do what you want. Try something like:
NSStringEncoding stringEncoding = NSUTF8StringEncoding;
NSString *personDesc = [NSString stringWithFormat:#"Person named %#", person.name];
const char *cPersonDesc = [personDesc cStringUsingEncoding:stringEncoding];
char *myArguments[] = { cPersonDesc, NULL };
// auth and tool already exist
AuthorizationExecuteWithPrivileges(auth, tool, kAuthorizationFlagDefaults, myArguments, NULL);
It's right. NSString is not char*. It is NSString. They have nothing to do with one another.
Since you give no indication of what you're really trying to do, no further advice can be given. You could convert NSString to char* if you wanted to, e.g. with getCString:maxLength:encoding:. But why would you want to?