Could not build module 'opencv2' , when using OpenCV in Swift Project - c++

I have added opencv framework through cocoapods. I added required frameworks to Linked Frameworks and Libraries as well.
As, I am using Swift. So, I made a bridging header with "Wrapper" NSObject in Objective C. Problem is that when I try to import these in Wrapper.h, it gives me error
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>
Error is:
Could not build module 'opencv2'
Where as if I import them in Wrapper.mm they work fine. Kindly tell me how to use them in header file. As I need to call a few variables from header file.

When bridging header files to Swift, the files have to be pure Objective-C++. So you cannot include any opencv headers in Wrapper.h, they have to go in Wrapper.mm. For more detail how to write and use a wrapper, see my answer here.

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>

Swift using static library compiled sources as Objective-C++

I am new to Swift. Recently I encounter a problem
There is a static library compiled sources as Objective-C++. For example, "import " in a .h file like:
#import <Foundation/Foundation.h>
#import <map>
#interface CppLib : NSObject
#end
Now I create a new swift project, include the .a and .h file created by the static library project. Add a new bridging file named "Swift_CppLib-Bridging-Header.h":
#ifndef Swift_CppLib_Bridging_Header_h
#define Swift_CppLib_Bridging_Header_h
#import "CppLib.h"
#endif
Then CMD+B, build the project failed:
/Users/air/Somnus/CodeDemo/Swift_CppLib/Swift_CppLib/Swift_CppLib-Bridging-Header.h:12:9: note: in file included from /Users/air/Somnus/CodeDemo/Swift_CppLib/Swift_CppLib/Swift_CppLib-Bridging-Header.h:12:
#import "CppLib.h"
^
/Users/air/Somnus/CodeDemo/Swift_CppLib/Swift_CppLib/Lib/CppLib.h:10:9: error: 'map' file not found
#import <map>
^
<unknown>:0: error: failed to import bridging header '/Users/air/Somnus/CodeDemo/Swift_CppLib/Swift_CppLib/Swift_CppLib-Bridging-Header.h'
Who could help me fix this problem? Thank for any hint!
You need to make sure that no c++ or objective-c++ is visible in the header that you're exporting to swift. Apple in their wisdom decided not to support c++ in swift. In my view this was a terrible decision on their part... but I don't work there so have no say in it :)
So you'll need to wrap the library in a thin obj-c wrapper unfortunately... or (IMHO) do the wise thing and avoid swift like the plague. It's just a convoluted syntactic sugar coating over objective-c and unfortunately you can't write a serious application in swift without fully understanding objective-c.
</rant> :)

Xcode 7 and openCV (no Swift): Core.hpp header must be compiled as C++

I have followed the instructions on how to install OpenCV on an iOS project. However when using Xcode 7 I had to add manually a prefix header. Doing this unfortunately did not help and I was still getting compile errors. I then read another post suggesting that is best to add manually the imports and not use prefix headers in Xcode 7, so I did.
Here is my code:
#import "ViewController.h"
#import <opencv2/opencv.hpp>
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <opencv2/highgui/cap_ios.h>
//using namespace cv;
#interface ViewController ()
{
IBOutlet UIImageView* imageView;
IBOutlet UIButton* button;
}
- (IBAction)actionStart:(id)sender;
#end
However I still get the following errors.
When I uncomment the using namespace cv; I get the following:
I found some complex solutions talking about exposing headers to Swift etc.. I just want my project to work on Objective-C with Xcode 7 ...
OpenCV is a C++ framework, which means that any code that makes use of OpenCV has to be compiled with C++ interpretation, rather than C interpretation.
The errors you see, e.g. with the using namespace cv; indicate that the code is compiled using the objective-C compiler, rather than the objective-C++ compiler.
As I mentioned in my comment the easiest way to get this to happen is to ensure that any file that #includes an opencv header must be named e.g. ViewController.mm, i.e. it must be an Objective-C++ file.
Alternatively, you can select and override the Type of the file, by explicitly selecting the Objective-C++ Source option for the file type in the utilities pane.
I just had the exact same problem. I'm working in a Swift project with OpenCV.
Regarding Swift, its entry point to OpenCV is a file I called OpenCVWrapper. So I got OpenCVWrapper.h and OpenCVWrapper.mm. In the bridging header of my project, I got #import "OpenCVWrapper.h".
Thing is I wanted to write a class called MatUtils in Objective-C++ that I could call from OpenCVWrapper.mm. For them to be seeable in there, I had to put them in MatUtils.h.
Long story short, the mistake is that in OpenCVWrapper.h, I did #import "MatUtils.h". MISTAKE!!!! As OpenCVWrapper is in the bridging header, C++ is now reachable from Swift!
Quick fix : #import "MatUtils.h" in OpenCVWrapper.mm!
Cheers!
bRo
The solution is almost the same as we do bridging ObjectiveC and swift but we do it between Objective C and C++ so we put the C++ codes in a separate file with (.mm) extension and then import it to your Objective C File (.m)
For example if you have ViewController.h and ViewController.m you add two more files which include your C++ codes lets name it OpenCV.mm and OpenCV.h then import the OpenCV.h inside ViewController.m even before you import anything else.
May be this image will help understand it:
Tested on Xcode 11.6 OpenCV Ver 3.4.3
Try placing #import < opencv2/opencv.hpp > before #import "ViewController.h".Source

Swift Compiler Error 'iostream' not found

I've tried to implement a project which I've found on github.
https://github.com/hossamghareeb/Facebook-POP-Tutorial
While I was implementing the .h and .m files I've got an error which was saying XCode could not find my 'iostream' file.
I'm working in SWIFT, using bridging-headers to use the framework. When I try to build the original project it works, but mine always fails.
How can I add my iostream file?
Thanks in advance!
Swift bridging does not support Objective C++ files. This means that any headers that consume or expose C++ entites (like std::vector; std::iostream) cannot be added to the bridging header.
The POP bridging header contains:
#import "POP.h"
You should really only #import that file in your own bridging header, rather than trying to #import all the .h files.
If you need to consume some of the API that's defined in .mm files that isn't exposed with an Objective C or plain C header, then you'll have to make your own header file that exposes it (and probably a back-end that implements what you've exposed).
The reason why you can use .mm files in a library that's being used by Swift is because all swift uses is the interface to those files - i.e. the .h files, and as long as those files are in plain C or Objective C, then you can make use of the code that is implemented in the .mm file. The .mm files are compiled by Objective C++ compiler (clang++)

osx coretext header for cpp files, pre-10.8?

It looks like before 10.8, CoreText was not a separate framework but was part of Cocoa.
I'm porting a bit of C++ code that wants to use CoreText types such as CTFontRef.
When I
#include <CoreText/CoreText.h>
I get a preprocessor error "CoreText/CoreText.h" not found. If I switch to something like
#import <Foundation/Foundation.h>
That works for .m or .mm, but not for .cpp files, since that includes Obj-C code.
Does anyone know what include to use for this case?
Use this include and you should be all set:
#include <ApplicationServices/ApplicationServices.h>
You may also need to include the "ApplicationServices" framework in your project as well.