How to access files in iOS project inside C++ function? - c++

So I call my C++ function through my OpenCVWrapper. In this function I have to open a file which is located in my Xcode project. Is it possible to specify the desired path in C++ function?
Or I have to pass a file through the OpenCVWrapper in Swift?
In short, it looks smth like:
func sample() {
OpenCVWrapper.booProcess()
}
in OpenCVWrapper.mm
#implementation OpenCVWrapper : NSObject
+ (void)booProcess {
boo();
}
- (void)boo:
{
return boo();
}
#end
blink.cpp
void boo()
{
cv::CascadeClassifier my_cascade;
my_cascade.load("bar.xml");
}
All necessary wrappers have been added.
enter image description here

I didn't find any proper way to get a file path in C++ function. So the most obvious solution is getting a String representation of the path in Swift.
let path = NSBundle.mainBundle().pathForResource("bar", ofType:"xml")
Then pass it through the wrapper to C++ function
OpenCVWrapper.booProcess(path)
In your OpenCVWrapper.mm you have to convert a NSString into a std::string like
std::string *mypath = new std::string([path UTF8String]);
Then you may pass this path to C++ function through the wrapper.
+ (void)booProcess:(NSString*)path {
std::string *mypath = new std::string([path UTF8String]);
boo(*mypath);
}

Unfortunately it is not currently possible to call C++ code from Swift. You will have to wrap OpenCVWrapper in Objective-C, and then call it in Swift.
See Using Swift with Objective-C for more info.

Related

Interacting with C++ classes from Swift

I have a significant library of classes written in C++. I'm trying to make use of them through some type of bridge within Swift rather than rewrite them as Swift code. The primary motivation is that the C++ code represents a core library that is used on multiple platforms. Effectively, I'm just creating a Swift based UI to allow the core functionality to work under OS X.
There are other questions asking, "How do I call a C++ function from Swift." This is not my question. To bridge to a C++ function, the following works fine:
Define a bridging header through "C"
#ifndef ImageReader_hpp
#define ImageReader_hpp
#ifdef __cplusplus
extern "C" {
#endif
const char *hexdump(char *filename);
const char *imageType(char *filename);
#ifdef __cplusplus
}
#endif
#endif /* ImageReader_hpp */
Swift code can now call functions directly
let type = String.fromCString(imageType(filename))
let dump = String.fromCString(hexdump(filename))
My question is more specific. How can I instantiate and manipulate a C++ Class from within Swift? I can't seem to find anything published on this.
I've worked out a perfectly manageable answer. How clean you'd like this to be is entirely based upon how much work you're willing to do.
First, take your C++ class and create C "wrapper" functions to interface with it. For example, if we have this C++ class:
class MBR {
std::string filename;
public:
MBR (std::string filename);
const char *hexdump();
const char *imageType();
const char *bootCode();
const char *partitions();
private:
bool readFile(unsigned char *buffer, const unsigned int length);
};
We then implement these C++ functions:
#include "MBR.hpp"
using namespace std;
const void * initialize(char *filename)
{
MBR *mbr = new MBR(filename);
return (void *)mbr;
}
const char *hexdump(const void *object)
{
MBR *mbr;
static char retval[2048];
mbr = (MBR *)object;
strcpy(retval, mbr -> hexdump());
return retval;
}
const char *imageType(const void *object)
{
MBR *mbr;
static char retval[256];
mbr = (MBR *)object;
strcpy(retval, mbr -> imageType());
return retval;
}
The bridge header then contains:
#ifndef ImageReader_hpp
#define ImageReader_hpp
#ifdef __cplusplus
extern "C" {
#endif
const void *initialize(char *filename);
const char *hexdump(const void *object);
const char *imageType(const void *object);
#ifdef __cplusplus
}
#endif
#endif /* ImageReader_hpp */
From Swift, we can now instantiate the object and interact with it like so:
let cppObject = UnsafeMutablePointer<Void>(initialize(filename))
let type = String.fromCString(imageType(cppObject))
let dump = String.fromCString(hexdump(cppObject))
self.imageTypeLabel.stringValue = type!
self.dumpDisplay.stringValue = dump!
So, as you can see, the solution (which is actually rather simple) is to create wrappers that will instantiate an object and return a pointer to that object. This can then be passed back into the wrapper functions which can easily treat it as an object conforming to that class and call the member functions.
Making It Cleaner
While this is a fantastic start and proves that it is completely feasible to use existing C++ classes with a trivial bridge, it can be even cleaner.
Cleaning this up would simply mean that we remove the UnsafeMutablePointer<Void> from the middle of our Swift code and encapsulate it into a Swift class. Essentially, we use the same C/C++ wrapper functions but interface them with a Swift class. The Swift class maintains the object reference and essentially just passes all method and attribute reference calls through the bridge to the C++ object!
Having done this, all of the bridging code is completely encapsulated in the Swift class. Even though we are still using a C bridge, we are effectively using C++ objects transparently without having to resort to recoding them in Objective-C or Objective-C++.
Swift has no C++ interop currently. It's a long-term goal, but is very unlikely to happen in the near future.
In addition to your own solution, there is another way to do it. You can call or directly write C++ code in objective-c++.
So you can create an objective-C++ wrapper on top of your C++ code and create a suitable interface.
Then call objective-C++ code from your swift code. To be able to write objective-C++ code you may have to rename file extension from .m to .mm
Do not forget to release memory allocated by your C++ objects when suitable.
You can use Scapix Language Bridge to automatically bridge C++ to Swift (among other languages). Bridge code automatically generated on the fly directly from C++ header files. Here is an example:
C++:
#include <scapix/bridge/object.h>
class contact : public scapix::bridge::object<contact>
{
public:
std::string name();
void send_message(const std::string& msg, std::shared_ptr<contact> from);
void add_tags(const std::vector<std::string>& tags);
void add_friends(std::vector<std::shared_ptr<contact>> friends);
};
Swift:
class ViewController: UIViewController {
func send(friend: Contact) {
let c = Contact()
contact.sendMessage("Hello", friend)
contact.addTags(["a","b","c"])
contact.addFriends([friend])
}
}
As another answer mentioned, using ObjC++ to interact is much easier. Just name your files .mm instead of .m and xcode/clang, gives you access to c++ in that file.
Note that ObjC++ does not support C++ inheritance. I you want to subclass a c++ class in ObjC++, you can't. You will have to write the subclass in C++ and wrap it around an ObjC++ class.
Then use the bridging header you would normally use to call objc from swift.

How To Call my Qt/C++ Dylib from Objective C?

I've compiled a dylib in Qt/C++. I created a simple class method called test() that reads a string input and returns a string output with "-response" back. Now how do I load that inside Objective C in XCode 7 (a default Cocoa application) and make it emit test() via NSLog()?
This is what my build folder looks like in Qt/C++.
You need to use an Objective-C++ class, which is a hybrid of Objective-C and C++.
The greatest challenge using one or more Objective-C++ classes in a largely Objective-C project is avoiding exposing C++ classes to the Objective-C classes. Therefore you need to avoid C++ in the Objective-C++ header file and just include the C++ in the implementation file.
For example:
CppWrapper.h:
#import <Foundation/Foundation.h>
#interface CppWrapper : NSObject
- (BOOL)callCppMethodA:(int)param;
#end
CppWrapper.mm:
#import "CppWrapper.h"
#import "cppclass.h" // C++
#interface CppWrapper()
{
cppclass *_cppclass; // C++
}
#end
#implementation CppWrapper
- (id)init
{
self = [super init];
if (self) {
_cppclass = new cppclass(); // C++
}
return self;
}
- (void)dealloc
{
delete _cppclass; // C++
}
- (BOOL)callCppMethodA:(int)param
{
return _cppclass->methodA(param); // C++
}
#end
Use it like this:
CppWrapper *cppWrapper = [CppWrapper new];
[cppWrapper callCppMethodA:123];
Another approach would be to not use Qt/C++, but create C++ classes inside of Objective C and avoid Qt altogether, opting for these includes to make life a whole lot easier in C++:
#include <string>
#include <stdio.h>
#include <sqlite3.h>
#include <Foundation/Foundation.h>
string docs
stdio docs
stdio notes
sqlite3 docs
Apple Foundation Class docs
Also, one can (and actually must) mix a little Objective C in their C++ code in order to make life easier. Here's a sample .mm file, which is the file type that lets you mix C++ and Objective C:
#include <string>
#include <stdio.h>
#include <sqlite3.h>
#include <Foundation/Foundation.h>
class Testlib {
public:
std::string test(std::string sIn) {
sIn = sIn.append("-response");
return sIn;
}
NS_RETURNS_RETAINED NSString *test2(NSString *sIn) {
// note [[funky Objective C syntax]]
NSString *sOut = [[NSString alloc] init];
sOut = [NSString stringWithFormat:#"%#-response", sIn];
return sOut;
}
};
In order for me to call this from my main.m file, I had to rename it to main.mm and then do something like:
#import <Cocoa/Cocoa.h>
#import "testlib.mm"
int main(int argc, const char * argv[]) {
// demo Testlib out to the debug log
Testlib *o = new Testlib();
std::string s = "";
s = o->test("request");
NSLog(#"Result=%s",s.c_str());
NSLog(#"Result2=%#",o->test2(#"request"));
// load our GUI
return NSApplicationMain(argc, argv);
}
So, for the most part, it gives the ease of use of C++, but makes it powerful with the SQLite3 and Apple Foundation Class stuff to do pretty much what one would have used Qt for (without having to include very large Qt runtime framework libraries). However, for the GUI -- Cocoa is pretty sparse on options (dare I say fascist) compared to Qt, which is why I opt to use Mac native WebKit inside Cocoa, which opens up a vast array of GUI styling. Also, by using Mac native WebKit instead of Qt's embedded WebKit, you can decrease the .app size by about 30MB.

how to write Objective C Wrapper for C++

I have a burning question on writing objective C wrapper for c++. That is an error in my code when i try to build it. I'm not sure what i have do it wrong. Would truly appreciate any help or guide. The following is the sample code that i have written:
///Print.h///
int test1();
///Print.cpp///
int test1()
{
printf ("hello man\n");
}
///cppWrapper.h///
struct Print;
typedef struct Print Print;
#interface cppWrapper : NSObject
{
Print *print;
}
#property (nonatomic, assign) Print *print;
-(id)init;
-(int)runTest;
///cppWrapper.mm///
#import "cppWrapper.h"
#implementation cppWrapper
#synthesize print = _print;
- (id)init
{
self = [super init];
if (self)
{
_print = new Print(); //error occurred here.
}
return self;
}
-(int)runTest
{
self.print->test1();
}
Objective-C wrapper for C++ is not implemented in terms of objective-C code.
To implement it, use pure C functions.
Under pure C functions, implement objective-C code. In C++ code, use C function to call objective-C code.
Objective-C does not understand C++.
Rather use Objective-C++ to use C++ code.
In objective-C++, you can use C++ code. Save your file as .mm rather than .m.
Edit:
The error in your code is because, the compiler is not able to find the definition of the structure. Compiler needs to know what is the size of the structure. Without its definition, it cannot create the object. This is also true even if you create object on stack.

Wrapping Objective C in Objective c++/c++

I've got a c++ app written using Boost/WXWidgets, targeting Windows and Mac OSX. However, I've got one issue that I can't solve using these libraries. My solution requires me to wrap an Objective C class so that I can call it from one of my c++ modules. My research so far tells me that I need to use Objective C++ written into source files with a .mm extension, allowing XCode to treat the file as a mix of Objective C and c++. I've found lots of articles detailing how to wrap c++ so that it can be called from ObjectiveC, but nothing that gives any detail on the reverse. Any links to articles or, better still, a worked example, would be greatly appreciated.
If you want a reusable pure C++ wrapper around an Objective C class, the Pimpl idiom works pretty well. The Pimpl idiom will make it so that there is no Objective C / Cocoa stuff visible in the header file that will be included by pure C++ code.
// FooWrapper.hpp
// Absolutely no Cocoa includes or types here!
class FooWrapper
{
public:
int bar();
private:
struct Impl; // Forward declaration
Impl* impl;
};
// FooWrapper.mm
#import "FooWraper.hpp"
#import "Foundation/NSFoo.h"
struct FooWrapper::Impl
{
NSFoo* nsFoo;
};
FooWrapper::FooWrapper() : impl(new Impl)
{
impl->nsFoo = [[NSFoo alloc] init];
}
FooWrapper::~FooWrapper()
{
[impl->nsFoo release];
delete impl;
}
int FooWrapper::bar()
{
return [impl->nsFoo getInteger];
}
Just mix it (but don't forget setting up the pool). It works.
// obj-c code, in .mm file
void functionContainingObjC(){
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc] init];
[lots of brackets!];
[pool release];
}
// c++ code, in .cc file
functionContainingObjC();
objc provides c interfaces for the basic interfaces and types (#include <objc/headers_you_need.h>. therefore, you can use these interfaces in pure c/c++ TUs. then include libs like Foundation or AppKit in the mm and use objc types and messaging in the implementation.
the following is a very basic interface which is not typesafe, but i encourage you to make it typesafe for the objc type you are wrapping. this should be enough to get you started in the right direction.
// .hpp
namespace MON {
// could be an auto pointer or a dumb pointer; depending on your needs
class t_MONSubclassWrapper {
public:
// usual stuff here...
// example wrapper usage:
void release();
private:
id d_objcInstance;
};
} /* << MON */
// .mm
...
#include <Foundation/Foundation.h>
MON::t_MONSubclassWrapper::t_MONSubclassWrapper() :
d_objcInstance([[MONSubclass alloc] init]) {
}
...
void MON::t_MONSubclassWrapper::release() {
[d_objcInstance release];
}

Iphone, callback and objective c

I am using a c++ library using callback to inform about the progress of an operation.
Everything is working fine except this:
I need to have a function in my controller to be use as a c++ callback function.
I've tried a lot of things but none of them are working.
Do you know how we can manage this kind of thing?
Thanks :)
iPhone APIs like the Audio Queue Services use a void * parameter in their callbacks, into which you can stuff your Objective-C instance.
If your C++ library has a similar setup - your callback gives a void * "context" parameter - you could do this:
void interruptionListener(void *inClientData, UInt32 inInterruptionState) {
InterruptionMonitor *self = (InterruptionMonitor *)inClientData;
[self inInterruption: inInterruptionState == kAudioSessionBeginInterruption];
}
So you use the inClientData to store your instance, and can then call methods on that instance that do the actual processing.
You have to define a c++-class in your .h with your callback methods, implementing the c++-interface. This class also keeps a delegate of your objC Class.
in your .m File after #end you specify the c++ methods. You may then use the delegate to perform selectors of your objC class
in .h
#interface YourObjcClass {
#ifdef __cplusplus
class FooObserver : public YourNS::Interface {
public:
virtual ~FooObserver() {
}
YourObjcClass *delegate;
};
YourNS::YourCallbackClass *myCallbackClass;
#endif
in .m
#ifdef __cplusplus
void FooObserver::callback( args ) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
[delegate performSelectorOnMainThread:#selector(performCallback)
withObject:nil
waitUntilDone:false];
[pool release];
}
#endif
There is a much better way of doing this. If you are already using boost in your iOS project you can use my objc_callback template: http://alex.tapmania.org/2012/04/c-to-obj-c-callbacks-part-2.html