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

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.

Related

Incompatible types casting 'NSString *' to 'CTStringRef *'

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;

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]

Incompatible pointer to integer conversion sending 'void *' to parameter of type 'NSEnumerationOptions' (aka 'unsigned int')

How do I specify that I want to 'enumerateObjectsAtIndexes:` without any options? When I try to pass nil to the options argument, Xcode gives me this warning. What is the equivalent value that won't cause a complaint?
opts is an enumeration which (in this case) is basically and unsigned int, so pass 0.
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Constants/Reference/reference.html#//apple_ref/doc/c_ref/NSEnumerationOptions
Read the NSArray docs on this method, then click the NSEnumerationOptions link in the description.
NSEnumerationOptions
Options for Block enumeration operations.
enum {
NSEnumerationConcurrent = (1UL << 0),
NSEnumerationReverse = (1UL << 1),
};
typedef NSUInteger NSEnumerationOptions;
Clearly it is an NSUInteger bit masked.
0 or one or both of the above, though the NSEnumerationConcurrent is noted to be a hint only and not guaranteed.
nil is not an NSUInteger. Not all method parameters are objects. nil should only be passed when an object parameter is optional.

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?

casting a block to a void* for dynamic class method resolution

+(BOOL)resolveClassMethod:(SEL)aSel {
NSString *lString = NSStringFromSelector(aSel);
if ([self validateLetterAndAccidental:lString]) {
id (^noteFactoryBLOCK)(id) = ^(id aSelf) {
return [self noteWithString:lString];
};
IMP lIMP = imp_implementationWithBlock(noteFactoryBLOCK);
...
I get an error at the last line because noteFactoryBLOCK is cast to a void* and ARC disallows that. Is there currently a way to accomplish what I want? I would like an IMP that I can pass to class_addMethod at runtime.
EDIT
IMP myIMP = imp_implementationWithBlock(objc_unretainedPointer(noteFactoryBLOCK));
This line give me a warning instead of an error - Semantic Issue: Passing 'objc_objectptr_t' (aka 'const void *') to parameter of type 'void *' discards qualifiers
I hate to say it but you might just have to cast away the const in this case.
IMP myIMP = imp_implementationWithBlock((void*)objc_unretainedPointer(noteFactoryBLOCK));
That is pretty ugly though.