问题
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++.
回答1:
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];
回答2:
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.
来源:https://stackoverflow.com/questions/34121291/how-to-call-my-qt-c-dylib-from-objective-c