Xcode and C++ Headers - c++

I have a question about using C++ header files in Objective-C++ modules in Xcode. Specifically, why can I #include them in source files but not header files?
Here is a specific example.
I'm using Xcode 7.2.1 and have two projects. The first is a C++ framework I package into "myFramework.framework". It exposes "myFramework.h", which in turn pulls in "myLib.h". At the top of "myLib.h" is an "#include <string>".
The second project is an Objective-C iOS app which consumes the above framework. In this project, "myViewController.mm" (Objective-C++ source) has "#import "myFramework/myFramework.h" at the top and makes reference to things defined in that header file.
At this point all is well and good. It builds and runs with no issues.
When I move the "#import myFramework/myFramework.h" line to "myViewController.h", the compile fails because it cannot locate the "" header dependency.
It doesn't matter if I change the file type for "myViewController.h" to Objective-C++ header from plain old "C Header". Either way, Xcode's header search paths don't look for standard C++ headers.
So my main question is why does it behave this way? Why is a #include/#import treated differently just because it's in a header file?
My second question is if there's some way to make Xcode treat the #include/#import the same when it's in the header file instead of the source file?
Thanks much!

Are you sure that you get the error while compiling the myViewController.mm file?
Check if myViewController.h is imported into some other, non ObjC++ file (and that that one is the file that fails to compile).

I suspect the issue with including C++ headers inside other headers is that an Objective-C source file gets to see the C++ header file, which upsets it.
If you have mixed C++/Objective-C++/Objective-C then you are probably better off only exposing a pure Objective-C interface to other modules in the project and include any C++ header files in the Objective-C++ source files only.
Alternatively make everything Objective-C++ and then you don't need to worry about it at all.
Hopefully this answers your second question as well.

Related

How to use Superpowered lib in Swift project

I want to make an app in Swift that simply record via the mic of the iPhone and then play the sound recorded.
For that, I'd like to use the lib Superpowered that is a static library with header files.
For that, I tried to drag and drop the .a and headers files in my project (Xcode create for me a bridging header file), add the .a in "Linked Frameworks and Libraries" in Xcode > Target > General (and so in Xcode > Target > Build phases > "Link Binary With Libraries" too) and index the .h files path in Xcode > Target > Build Settings > Search Paths > Library Search Paths.
But with that I have the error "ld: symbol(s) not found for architecture arm64"
Exactly the same as here XCode: Undefined symbols for architecture arm64 error and I tried all the solutions that I found on the web for that, still no way to compile.
SO !
Superpowered gives us a sample app to show how to mix Objective-C++ and use their lib within a Swift project (Here's a link to the git if you want https://github.com/superpoweredSDK/Low-Latency-Android-Audio-iOS-Audio-Engine).
Here is some screenshots of the sample project with what I understand and what I don't :
The Bridging-Header-File with the prototypes of the methods of the lib that I want to use within my Swift code (I don't like this but if it's the only way...).
The viewController file where the code in Swift is, and where I can create a Superpowered object thank's to the Bridging-Header-File, and call the methods that I've put in it.
And wtf I don't even understand why this Objective-C++ file is here and what it contains. It comes out from nowhere, not even their lib files.
So with this sample project in mind, I've created my own project, here is some screenshots :
The same Bridging-Header-File that in the sample project except that I include SuperpoweredIOSAudioIO.h so I can use SuperpoweredIOSAudioIODelegate.
My viewController file where the code in Swift is, and where I can create a Superpowered object thank's to the Bridging-Header-File, and call the methods that I've put in it.
Until here, it's great, except that I can't for exemple create a SuperpoweredRecorder object. If I try to include the SuperpoweredRecorder.h file in my Bridging-Header-File I have these errors :
So I saw that it is because SuperpoweredRecorder.h includes some .cpp files and I have to create a wrapper for cpp (a little bit like I did with the bridging header, no ?) but that includes a .h and a .mm file and I don't know what I have to put in that .mm file (the code of SuperpoweredRecorder.cpp ? But I don't have access to it)
So yes, I'm a little bit confused with all that stuff, can you help me to understand how can I use all the Superpowered lib in my Swift project please ?
As I said in comment to #OmniProg, I had a little conversation with the CTO of Superpowered that helped me a lot to find the solution below.
So, as Swift cannot interact directly with C++ but can with Objective-C, I had to create objects in Objective-C++ (.mm file, a mix between C++ and Objective-C) that wrap C++ classes of the lib Superpowered.
Here is an example with the SuperpoweredRecorder object from the lib :
Here I create a .h file where I prototype my wrapper with the name SuperpoweredRecorderWrapped, and I also prototype in it all the methods of the SuperpoweredRecorder of the lib that I want to use.
Then I create a new .m file that I rename .mm and I implement SuperpoweredRecorderWrapped on it.
I import both SuperpoweredRecorderWrapped.h and SuperpoweredRecorder.h.
I create a SuperpoweredRecorder object as property named _wrapped and in my methods, I call the corresponding method of the _wrapped object.
With that, when I'll call start of a SuperpoweredRecorderWrapped in my Swift code, this one will call start of _wrapped, a SuperpoweredRecorder object. See the trick ?
And finally I include all the wrapped classes in my Bridging-Header, like that I can instantiate my wrapped objects from Swift.
NOTE: All the C++ code HAVE to be in .mm files, that's why I make my #include of .h that contains C++ code in my .mm file and not in my .h file.
I haven't programmed in Objective-C++, but I do have experience with C, C++, Objective-C, and Swift, so here are some observations and ideas based on looking at the Superpowered SDK and sample code.
A bridging header lets Swift interface directly with Objective-C, and since Objective-C is a strict superset of C, this implies interfacing with C as well. However, you cannot interface directly with C++, and that's where Objective-C++ comes to the rescue. From what I'm seeing you can mix Objective-C and C++ code in Objective-C++, which allows Objective-C to use C++ classes.
Now on to some specifics.
The bridging header in the SuperpoweredFrequencies example that you looked at introduces a new Objective-C class, Superpowered, which is not part of the library, but of the example, and is implemented in Superpowered.mm. It is an Objective-C++ file, because Superpowered calls some C++ code.
Looking at Superpowered.mm, you will see that it imports Objective-C headers:
#import "SuperpoweredFrequencies-Bridging-Header.h"
#import "SuperpoweredIOSAudioIO.h"
as well as C and C++ headers:
#include "SuperpoweredBandpassFilterbank.h"
#include "SuperpoweredSimple.h"
We could have used import instead of include for C++ code, too, but they are probably using include just to emphasize that it is C++ code. Looking at SuperpoweredBandpassFilterbank.h, we see that SuperpoweredBandpassFilterbank is a C++ class. It is used in Superpowered.mm by the Superpowered Objective-C++ class, see the filters member, which is a pointer to a SuperpoweredBandpassFilterbank object.
In the project you attempted to build, I see where the Superpowered interface is declared in the bridging header, but I don't see an implementation. The failure to #import SuperpoweredRecorder.h is due to SuperpoweredRecorder.h being a C++ header. The #include should be in your Objective-C++ (.mm) file, it's useless in the bridging header, since Swift can't make sense of C++ anyhow.
Hopefully this is helpful. Welcome to the world of C++.
I'm a bit surprised that you would have to provide prototypes of method.
I used Objective C libraries in my Swift project before and I only had to add the header files in my bridging header.
See example from my project. The bridging header contains just that:
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "QTouchposeApplication.h"
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <FBSDKLoginKit/FBSDKLoginKit.h>
#import <VungleSDK/VungleSDK.h>

How to handle non-ARC code in header file?

My project structure
MainProject (ARC)
SubProject(Non-ARC)
Boost library(i.e. Popular C++ library here is a link http://www.boost.org/)
Problem :
One of header file(intrusive_ptr.h) of Boost library has a inline function with "retain" statement(That file is edited by someone and it is working fine in "SubProject(Non-ARC)"). That header file is public, many files of subporjects are imported in "MainProject" and those file has a reference of this header file. So, indirectly that file comes in MainProject which is an ARC based. That's why compiler refuse to compile.
What I know or tried:
I know how to set the non ARC flag but that we can set only for .m file(compilable file only) not on .h file. if somebody could help me or suggest me any out of box solution.
For the persons who are interested in seeing the "intrusive_ptr.h" can find here intrusive_ptr.h. This file is a part of boost library so, suggestion should consider this library as well.
Any help or directions will be appreciated.
You can use the preprocessor to alter your header file using the technique from this answer
#if __has_feature(objc_arc)
//ARC-specific things
#else
//Non-ARC specific things
#endif
If you need Boost facility in some classes you can hide that using Objective-C++. Helper links:
http://philjordan.eu/article/strategies-for-using-c++-in-objective-c-projects
http://support.apple.com/kb/TA45902?viewlocale=en_US

xcode 4.6 iostream file not found error?

I am facing a problem regarding iostream file not found in header file.I just added a c++ file in my project a header file also included by default with some macro definition and including iostream file as
#ifndef __ObjectiveCPlus__File__
#define __ObjectiveCPlus__File__
#include <iostream>
#endif
but at this line I am getting error at include line as
I google it a lot and found various types of answer regarding this.But no one is able to correct my errors.
Please help
Thanks!
You don't need <iostream> in your header file, put it in your .cpp file. You're not referring to anything in the iostream library in your header file, using this library is more of an implementation detail.
Why?
I believe UIAppDelegate imports UIViewController.h, that includes MathUtils.h. Because UIAppDelegate's implementation is in a .m file, it's being compiled for Objective-C, and this chain of includes (which is all based on the header files) is including something that is C++. As such, the Objective-C portion is unable to find <iostream>, as that library does not exist in pure Obj-C.
Putting it in your .cpp file limits it to one compilation unit, the MathUtils unit. Having it in your header file includes it in all compilation units that have a dependancy on whatever is using it, which may not be Objective C++.
Alternative Solution
You could have your whole project as Objective C++ (in this case, by changing UIAppDelegate.m to UIAppDelegate.mm), which means C++ can be used throughout. I'm not a fan of this method, and it could mask bad coding practices.
I got the solution from another post:
Renaming your implementation file with .mm extension instead of .m will solve the issue.

LLVM refuses to compile C++ source, weird errors

I've made a struct which does cached file manipulation for my application. I built and tested to in a separate project before putting it into my current one.
Ever since I've moved it over, Xcode refuses to build it. Except when I don't include the file from any Objective-C based header file.
I get one error when I try to include iostream:
And more when I comment it out:
Its file extension is .mm, however I have tried it with .cpp and .hpp, but all of them refuse to build unless I don't #include it from the Objective-C header file.
I've also tried #import from iostream and the file itself in the Objective-C header file.
Any clues as to why this is happening?
As a matter of principle, you cannot include a C++ header file from an objective-C source file.
After all, #including (or #importing) a file only means that the preprocessor replaces the #include directive by the contents of the #included file, before passing the result on to the "actual" compiler. The file extension of the header file is a matter of convention, only, it has no actual meaning.
The error messages your are seeing are clearly the result of the file being compiled as [Objective-]C rather than [Objective-]C++.
Solution: All the source files that include your C++ header file have to be either C++ (.cpp or .cc or a few other extensions) or Objective-C++ (.mm). All source files that include a header file that includes your C++ header file, also have to be C++ or Objective-C++.
EDIT: I just saw that you are defining non-inline, non-template functions in your C++ file that you want to include. This is an unrelated problem, but it will lead to "multiple definition" errors sooner or later. Those function definitions belong in a .cpp, which shouldn't get #included anywhere, only the struct/class definition belongs in a header.
Take a look here and here. You need to tell the compiler to include libstdc++. When mixing Objective-C and C++ all you're files need to have the ".mm" extension, as stated in the second link.
I suspect the error is occurring when you compile a .m or .c file that includes the same header.

Compiler can't find frameworks anymore after moving to objective-c++

I am extending a current c++ project with objective c code. For this purpose I compile the code as objective-c++ code. But since i changed the ending of a .cpp file into .mm, the compiler can't find two includes anymore.
One is a framework (#include <QTime>) and the other a simple header (#include "timecoder.h"). I changed the path of timecoder.h to its relative path and the compiler didn't complain anymore. But the problem with QTime still persists.
Do you have any idea what i could do?
Try using #import instead of #include.