Any disadvantages of using Objective C objects / types in a C++ class (.mm file)? - objective-c

Are there any disadvantages (performance or otherwise) to using Objective C objects within a C++ class with Objective C++ files? For example, the difference between using Objective C types such as NSString directly like so:
class Hello {
private:
NSString *text;
public:
Hello() { this->text = #"Hello, world!";
~Hello();
NSString* helloWorld() { return this->text; }
};
versus using standard lib C++ strings and wrapping them into NSStrings afterward. Is there any reason that directly using Objective C "types" is inferior? I've heard people recommend to keep Objective C and C++ as separate as possible and I'd like to hear the rational behind that. Either way I'll be hiding the C++ class behind a Objective C interface regardless to call it from .m files.

I don't think there is any problem with performance, however it's not clear to me why you would want to encapsulate Objective-C objects within a C++ object.
One reason to keep C++ purely C++ is so it can interact with other C++ objects, which is no longer possible once you include Objective-C objects.
In order to allow a C++ object, with an embedded Objective-C object, to be used by another C++ class (where it needs to "see" the header file) I guess you'd have to use void * or something.

Related

Prevent Subclassing Objective-C Classes in Swift

I'm adding Swift interior annotations to my Objective-C classes. I'm trying to prevent my class from being subclassed:
__attribute__((objc_subclassing_restricted))
#interface CWTestFinalClass : NSObject
#end
This works as expected in Objective-C:
// Generates Error, as expected
#interface CWTestSubclass : CWTestFinalClass
#end
However, I'm still able to subclass in Swift
// Should fail, but works without error
class TestSubclass: CWTestFinalClass {
}
Question: How do I prevent Objective-C classes from being subclassed in Swift?
Objective C does not have a final keyword, or anything like it. Even if a compile-time attribute or modifier did exist, it could trivially be sidelined by the use of the runtime APIs to dynamically create a subclass of any psuedofinal class.
The Swift compiler enforced that Swift could block attempts to subclass a final class, but that wouldn't stop Objective C from being able to do so (which isn't compiled through the Swift compiler). Thus, the objc_subclassing_restricted attribute was added, specifically to make clang enforce the illegality of subclassing final Swift classes.
There really isn't much of a benefit to making Objective C classes final, even if it were possible. Objective C is a much more dynamic language, that seems to follow Python's "we're all adults here" mantra.
The biggest reason to support final classes is inform the compiler which classes are candidates for de-virtualization. But Objective C always uses dynamic dispatch, and never does de-virtualization, anyway.

Objective-C Blocks in C

While reading through the blocks conceptual overview in Apple Docs, I saw the following statement:
Although blocks are available to pure C and C++, a block is also
always an Objective-C object.
How is this possible? I mean an Objective-C object available in pure C. I'm getting confused.
How is this possible? I mean an Objective-C object available in pure C.
Matt Gallagher wrote an article that nicely explains how blocks work. In a nutshell, blocks are defined as structs that meet the requirements to be a valid Objective-C object (for example, the struct starts with an isa pointer). None of this causes a problem for C, and the compiler knows what the definition of a block is, so even when compiling plain old C it can still do the right thing to make blocks work.
The added Objective-C aspect of blocks doesn't affect how blocks are used in C, but still provides the ability to treat blocks as objects so that they can be added to collections and otherwise managed like any other object.
This isn't really so strange. If you think about it, all Objective-C objects are "available" in C at some level -- the entire Objective-C runtime consists of C functions that manipulate structures that represent Objective-C objects and classes. And even disregarding that, blocks aren't the first example of a data type that's usable in both C and Objective-C -- we've had toll free bridging between Foundation and Core Foundation for many years. The implementation of blocks may be somewhat different, but it's not a new thing to have objects that work in both worlds.
Objective-C can be freely mixed with C. As long as your class has a C API (which blocks do, with Block_copy, Block_release, etc.), the C code doesn't care if it's implemented in Objective-C or C.
From the same document,
float (^oneFrom)(float);
oneFrom = ^(float aFloat) {
float result = aFloat - 1.0;
return result;
};
oneFrom a variable referencing the block (object) { float result = aFloat - 1.0; return result; }
Blocks are available to pure C and C++, ie. the block can consist of pure C or C++ code.

Generate ObjC code using LLVM

I have been reading this article on implementing fast forwarding in Objective C using LLVM and had an idea for doing something similar. Is it possible to generate Objective C code to extend an existing class using LLVM? I have a class definition. Now I want to add a new message to that class using LLVM. Would that be possible?
Well, you can do this with the Runtime library, add methods etc....Runtime Reference
Look at...
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

Objective-C reference to a pointer declaration getting error

I had this declaration.
- (BOOL)getNHPData:(REMOTE_MESS_ID)msgId withEvent:(RSEvent*&)pEvent;
I tried with RSEvent** also but i'm getting this error for 2 times
Expected ')' before RSEvent
Why is it so.
Objective-C is a superset of the C language and does not have references. If you want to use C++-style references in Objective-C, you must compile as Objective-C++ (as you might expect, Objective-C++ is a superset of C++). Use the .mm extension to automatically use the Objective-C++ in Xcode.
If the method in question is a public API that will be consumed from Objective-C, I would highly recommend using a pointer-to-pointer (RSEvent**) instead of a pointer reference. Using Objective-C++ in a header "infects" clients with Objective-C++ (unless you're very careful). Objective-C++ takes much longer to compile that Objective-C and you will eventually run into the inevitable C vs. C++ incompatibilities. Standard practice is to hide Objective-C++ from public APIs whenever possible.
I personally have never had much success in c++ or obj-c with pointer references, if I need that kind of functionality, I usually just use a pointer pointer like this:
some function()
{
RSEvent *pEvent = new RSEvent();
[self getNHPData:DEFAULT_MSG_ID withEbvent:&pEvent];
}
- (BOOL)getNHPData:(REMOTE_MESS_ID)msgId withEvent:(RSEvent**)pEvent
{
//Do some stuff
}

turning an objective c object into a c++ object so i can pass it into a parameter for CFNotification

i have a .m class written in objective c that needs to send information to a .mm class written in c++
i tried to use CFNotification and as far as i can tell the notifcation sent by the .m class can be picked up by the .mm class
the problem now is trying to get information across in that notification.
The documentation says i need to pass the info as a CFDictionary, i'm having a lot of trouble trying to create the dictionary...
the problem is due because of the second and third parameter. They require a const void** type...
which is a c++ array (right?) and i can't make a c++ array that contains some objective c objects
i tried making a c++ class in another .mm file but i can't include that in the .m file because i get compile errors saying there is stuff wrong with the syntax. if i change the .m file to a .mm file i get rid of those errors but i get a whole lot of other errors from the openGL and a few other conversion compile errors
... i tried making a .m wrapper for the .mm file so i can send and receive NSNotifications but i get a stupid error saying i've tried to redeclare the type of the wrapper but only when i tried using it...
The easiest solution to your problem is to forget about Objective C files and C++ files and switch to using Objective C++ files (extension .mm) for everything. You can alternatively tell Xcode to compile everything as Objective C++ irrespective of file extension.
Then use the fact that NSNotificationCenter and CFNotificationCenter interoperate, so you can use whichever you prefer at the time, or since your code is now all Objective C++, you can use either one exclusively from everywhere.
Follow that up with the fact that NSDictionary* and CFDictionaryRef are toll free bridged, as are NSString* and CFStringRef. That is to say, anything that accepts a CFDictionaryRef as a parameter can be passed an NSDictionary* cast to a CFDictionaryRef and vice versa.
So if you have an NSDictionary with NSString keys and values you can equally treat that pointer as a CFDictionaryRef with CFStringRef keys and values.
Okay, you're making this way harder than it needs to be.
So you want to send a notification with Objective-C? Use NSNotificationCenter. That's it, you're done. Don't use CFNotificationCenter. Actually, they're the same thing, but you shoud use the NSNotificationCenter interface from Objective C and only use the CFNotificationCenter interface when you need to write something in plain old C -- approximately never, if your app already has Objective C in it.
The void const** isn't necessarily a C++ array, either. And yes, you CAN put Objective-C objects in normal C arrays. For example:
NSString *const MESSAGES[2] = { #"Hello", #"Goodbye" };