Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link?
Usually you simply wrap your Objective-C classes with C++ classes by e.g. using opaque pointers and forwarding calls to C++ methods to Objective-C methods.
That way your portable C++ sources never have to see any Objective-C includes and ideally you only have to swap out the implementation files for the wrappers on different platforms.
Example:
// c++ header:
class Wrapper {
struct Opaque;
Opaque* opaque;
// ...
public:
void f();
};
// Objective-C++ source on Mac:
struct Wrapper::Opaque {
id contained;
// ...
};
void Wrapper::f() {
[opaque->contained f];
}
// ...
How to call C++ method from Objective-C Cocoa Interface using Objective-C++
I found a solution by noting that there was an existing wrapper class CWrapper.h
and it was an objective-C++ implementation class CWrapper.mm
. There was a CMain
variable instantiated as cmain
. I made a getter method for x
and I simply created a static method in the wrapper class + (void) passX:(int) number;
that I called in the slider class. I chose a static method because this for this application, this value will never have to be different between objects. I hope I made the right choice here!
See code changes below:
I added this to the Slider.h
file.
- (int)X;
I added the getter and [CWrapper passX:[self getX]];
to the updateSliderValue
method in the Slider.mm file.
- (int)X {
return [slider intValue];
}
- (IBAction)updateSliderValue:(id)sender {
[sliderValue setIntValue:[slider intValue]];
[CWrapper passX:[self getX]];
}
This is the code I added to CWrapper.h.
+ (void) passX:(int) number;
This is the code I added to CWrapper.mm.
+ (void) passX:(int)num
{
cmain.setValueofX(num);
}
Moving functions to separate classes
If you are wondering were to put C functions like the one you are describing, the best practice is to move them into a separate .h file that has a meaningful name. For instance MyGeometry.h
Make sure you give a descriptive name to your function, such as:
static inline CGPoint CGPointMakeRandom() {
// your code
return point;
}
How to handle objective-c delegation from C++?
Ok to answer your question:
reportwindow.h is additionally included in a .cpp file, if that makes
a difference.
It does make a difference. Any compilation unit (cpp file in this case) that is touching Objective-C code has to be renamed to .mm or .m. Including the header that in turn is including Objective-C stuff in a C++ file will lead to the problem that the C++ compiler sees Objective-C code which it cannot handle.
Renaming the cpp file to mm will select the Objective-C option during compilation (which isn't when the file is named cpp or c) and hence allow to compile stuff with the Objective-C tokens (mainly "@" in your case).
An alternative would be not to include the Objective-C delegate class to your C++ class but rather include a pointer to your C++ class within the Objective-C delegate (i.e. implement it the other way around). This way you could arrange things such that the Objective-C code isn't touching the C++ code.
Edit: Actually, I'd prefer the second suggestion. Here is an example:
DelegateClass.h:
class MyCPPClassHandlingStuff;
@interface MyDelegateObject : NSObject <SomeDelegateProtocol> {
MyCPPClassHandlingStuff *m_handlerInstance;
}
- (id) initWithCPPInstance:(MyCPPClassHandlingStuff*)cppInstance;
- (void) theDelegateProtocolMethod;
@end
DelegateClass.mm
#include "MyCPPClassHandlingStuff.h"
@implementation MyDelegateObject
- (id) initWithCPPInstance:(MyCPPClassHandlingStuff*)cppInstance
{
self = [super init];
if (self) {
m_handlerInstance = cppInstance;
}
return self;
}
- (void) theDelegateProtocolMethod
{
if (m_handlerInstance)
m_handlerInstance->handleDelegateMethod();
}
@end
And well the MyCPPClassHandlingStuff.h:
#ifndef __MyCPPClassHandlingStuff_H__
#define __MyCPPClassHandlingStuff_H__
class MyCPPClassHandlingStuff
{
public:
MyCPPClassHandlingStuff();
void handleDelegateMethod();
};
#endif /* __MyCPPClassHandlingStuff_H__ */
MyCPPClassHandlingStuff can be initialized from Objective-C but you cannot initialise any Objective-C class from C++ code there. If you need to use Objective-C in your C++ code, you would have to compile it as Objective-C (i.e. use an .mm file). I leave the .cpp details as an exercise for the reader ;)
Objective C Class Methods vs C Functions
In short, C (or C++) implementations are very useful:
- For Abstraction
- For Reusability
- When making medium and large scale programs
- In performance critical paths
- For 'Interior' implementations
What benefit exists (other than coding style) for favouring a C function over a class method?
- ObjC messaging introduces indirect function calls. These are firewalls for optimizers.
- C functions can easily restrict access, whereas 'private' ObjC implementations may be looked up using the ObjC runtime, or accidentally overridden.
- C functions may be removed from your executable if not referenced, or they may be made private. If you write reusable code (and you should), this can have a huge impact on your binary sizes and load times -- C functions which are not referenced/used may be removed, but ObjC types and methods will be preserved (including everything they reference). This is why your app's binary size may grow significantly when you use only small part of an ObjC static library -- every objc class in the library is preserved. If that library were C or C++, then you could get by with very small growth because you need only what is referenced. What is or is not referenced is easier to prove with C and C++.
- C functions can be inlined, either during compilation or during Link Time Optimization phases.
- The compiler and optimizers are able to do much optimization with C functions (e.g. inter-procedural optimizations), but very little with ObjC methods because they are always indirect.
- To avoid ObjC message dispatch overhead (as you mentioned)
- Potential for additional reference counting operations and autorelease pool activity when interacting with ObjC objects.
Of course you won't always hurt paying for things you don't need or use -- and remember that ObjC class methods have some benefits over C functions, too. So, just look at C or C++ implementations as another tool in your toolbox. I find them very useful as complexity and project sizes increase, and they can be used to make your programs much faster. Just do what you are least likely to regret in 2015 ;)
How to write objective c wrapper for c++ methods?
You should read up on "compilation units". In short, there's no way to tell what language a header file is written in for the compiler. Therefore, it always uses the language of the source file that includes the header. So if you include a C++ header from a .m
file, it will not work. For every ObjC file that uses a C++ header, you have to change the file name suffix of the source file that uses it from .m
to .mm
. You do not need the source files for your rubberband library, you simply need to make all the files that use it ObjC++ instead of just ObjC.
Of course, you may not want to change all your files to be ObjC++. Your code for the alternate approach of wrappering the C++ is pretty close. One thing I noticed is that you still have the <#foo#>
placeholders in your code (Xcode may display them as blue rounded cartouches, which is probably why you haven't noticed them before). Replace those with the actual names of the parameter variables, just like you would with a regular C function call, and all should compile. I.e.:
-(void)process:(const float)input samples:(size_t)samples final:(bool)final {
static_cast<RubberBand::RubberBandStretcher *>(myRubberBandStretcher)->process( input, samples, final );
}
Also note that you seem to have omitted the semicolon after the process
call.
BTW, you can also get rid of having to use static_cast
everywhere, see the tricks listed here: Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link? and there might also be some more useful info here: How to call C++ method from Objective-C Cocoa Interface using Objective-C++
Recommend way to use a large C++ library in a Cocoa application?
You can easily mix C++ and Objective-C using Objective-C++. In XCode just rename your .m files to .mm and it will recognize the files as Objective-C++. Then you can use the C++ classes in your Objective-C code (some restrictions apply, but not many).
Since Objective-C is an extension to C you can use C libraries in any Objective-C program easily.
How to wrap a C++ lib in objective-C?
My recommendation is to wrap the C++ bits in #ifdefs:
//MyWrapper.h
#ifdef __cplusplus
class ComposedClass;
#endif
@interface MyWrapper : NSObject
{
#ifdef __cplusplus
ComposedClass *ptr;
#endif
}
// wrapped methods here...
@end
This is a slightly lame version of the PIMPL idiom, but less code, and effective for hiding C++-isms from your pure Objective-C code. Obvioulsy you would have to include the ComposedClass
's header in your MyWrapper.mm
.
If ComposedClass
is a templated type, you will need to modify the first block to
#ifdef __cplusplus
#include "ComposedClass.h"
#endif
instead of using a forward declaration and then, of course, use the templated type in your Objective-C class' instance variable declaration.
This approach was suggested by Greg Parker, the runtime guru at Apple.
Related Topics
How to Add a Timed Delay to a C++ Program
When and How to Use Exception Handling
Std::Shared_Ptr Thread Safety Explained
What Is the Best Encryption Library in C/C++
Why Is It Undefined Behavior to Delete[] an Array of Derived Objects via a Base Pointer
How Is a Vector's Data Aligned
How to Check If an Object's Type Is a Particular Subclass in C++
Simple Object Detection Using Opencv and MAChine Learning
When and How to Use Gcc's Stack Protection Feature
How to Initialize C++ Object Member Variables in the Constructor
Is There Any Case Where a Return of a Rvalue Reference (&&) Is Useful
Structure of a C++ Object in Memory VS a Struct
When Is an Object "Out of Scope"