Как вызвать мой Qt/C++ Dylib из Objective C?

Я скомпилировал dylib в Qt/C++. Я создал простой метод класса с именем test(), который считывает ввод строки и возвращает вывод строки с "-response" назад. Теперь, как мне загрузить это в Objective C в XCode 7 (приложение Cocoa по умолчанию) и заставить его испускать test() через NSLog()?

Вот как выглядит моя папка сборки в Qt/C++.

введите здесь описание изображения


person Volomike    schedule 06.12.2015    source источник


Ответы (2)


Вам нужно использовать класс Objective-C++, который представляет собой гибрид Objective-C и C++.

Самая большая проблема при использовании одного или нескольких классов Objective-C++ в проекте, в основном написанном на языке Objective-C, заключается в том, чтобы не подвергать классы C++ воздействию классов Objective-C. Поэтому вам нужно избегать C++ в заголовочном файле Objective-C++ и просто включать C++ в файл реализации.

Например:

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

Используйте это так:

CppWrapper *cppWrapper = [CppWrapper new];
[cppWrapper callCppMethodA:123];
person trojanfoe    schedule 06.12.2015
comment
Является ли cppclass.h заголовочным файлом из моего класса Qt/C++? И как мне включить связь dylib в мой проект ObjC? И какой файл я должен использовать — я предполагаю, что это libtestlib.1.0.0.dylib? - person Volomike; 06.12.2015
comment
Я запутался. Я зашел в XCode7 и добавил инфраструктуру libtestlib.1.0.0.dylib в раздел «Связанные платформы и библиотеки». Затем я добавил в проект файл .h. Затем в моем файле main.m я добавил import "testlib.h". Он видит testlib, но класс почему-то не виден. Все, что я вижу, это: TESTLIBSHARED_EXPORT. - person Volomike; 07.12.2015
comment
Да, похоже, вы идете в правильном направлении, добавляя .dylib в Link Libraries and Frameworks, однако, если testlib.h определяет класс C++ (или функции или использует классы C++), вам нужно будет переименовать main.m до main.mm. - person trojanfoe; 07.12.2015
comment
Я все еще застрял: forum.qt.io/topic/61451/ - person Volomike; 07.12.2015
comment
@Volomike Это утверждение не будет работать: NSLog(@"Result=%@",o->test('request'));, при условии, что o->test() возвращает const char * или что-то вроде %@ в строке формата NSLog(), будет ожидать объект Objective-C. И что такое 'request'? Это не веревка что ли... - person trojanfoe; 07.12.2015
comment
У меня есть образец загрузки для этого проекта, и я изменил 'request' на "request". Он не будет компилироваться. Может быть, вы разберетесь? volosites.com/downloads/sample.zip - person Volomike; 09.12.2015
comment
Я думаю, что попробую этот подход. - person Volomike; 09.12.2015

Другой подход заключается в том, чтобы не использовать Qt/C++, а создавать классы C++ внутри Objective C и полностью избегать Qt, выбирая их, чтобы сделать жизнь намного проще в C++:

#include <string>
#include <stdio.h>
#include <sqlite3.h>
#include <Foundation/Foundation.h>

строковые документы

стандартные документы

примечания стандартного интерфейса

документы sqlite3

документы Apple Foundation Class

Кроме того, можно (и даже нужно) добавить немного Objective C в свой код на C++, чтобы облегчить себе жизнь. Вот пример файла .mm, который позволяет смешивать C++ и 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;
  }

};

Чтобы я мог вызвать это из моего файла main.m, мне пришлось переименовать его в main.mm, а затем сделать что-то вроде:

#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);
}

Таким образом, по большей части он обеспечивает простоту использования C++, но делает его мощным с помощью материалов SQLite3 и Apple Foundation Class, чтобы делать в значительной степени то, для чего можно было бы использовать Qt (без необходимости включать очень большие библиотеки среды выполнения Qt). ). Тем не менее, для графического интерфейса — Cocoa довольно скуден по параметрам (осмелюсь сказать, фашистским) по сравнению с Qt, поэтому я предпочитаю использовать родной Mac WebKit внутри Cocoa, который открывает широкий спектр стилей графического интерфейса. Кроме того, используя собственный WebKit Mac вместо встроенного WebKit Qt, вы можете уменьшить размер .app примерно на 30 МБ.

person Volomike    schedule 09.12.2015