Objective-C и С++ в Xcode

Если вы разрабатываете приложения для Mac и iOS на Objective-C или Swift, это не означает, что вы можете использовать только эти языки программирования. Очень часто возникает ситуация, когда вам нужно подключить к проекту модули на C++ или C. Xcode и LLVM компилятор позволяют это делать. Далее я расскажу как вызвать  С+ метод из Objective-C, предать в него параметры, и из C++ метода вызвать Objective-C и вернуть в него результаты.

Итак!

Как подружить Objective-C и C++ в Xcode?

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

Создаем новый проект.

Objective-C и С++ в Xcode

Создадим класс SearchManager, который будет представлять собой Синглтон и отвечать за взаимодействие с моделью поиска.

SearchManager.h

SearchManager.m

Мы реализовали классический синглтон.

Создаем модель нашего поиска на C++. File->New File->C++ File. Вводим название файла cppsearch и отмечаем галочку Also create a header file

Objective-C и С++ в Xcode

Реализуем наш поиск в виде метода void performCppSearch(const char* searchTemplate, const char* searchPath);

cppsearch.hpp

cppsearch.cpp

Отлично. Теперь нам необходимо реализовать вызов С++ метода performCppSearch из нашего Objective-C менеджера поиска. Теперь внимание. Первое , что мы делаем, – подключаем заголовочный C++ файл директивой #include(!) Не #import, а #include, – иначе компилятор выдаст ошибку “Undefined symbols for architecture x86_64:” И реализуем вызов поиска через метод

– (void)performSearchWithTemplate:(NSString *)searchFile withPath:(NSString *)searchPath

В итоге класс нашего Менеджера поиска приобретает следующий вид:

SearchManager.h

SearchManager.m
В методе performSearchWithTemplate:withPath: мы приводим шаблон поиска и путь из NSString* к char* и передаем их в C++ метод, который вызываем отдельным потоком.

В принципе первая часть задачи выполнена. Запускаем и… Получаем ошибку компиляции. Дело в том, что нам необходимо переименовать SearchManager.m в SearchManager.mm. Расширение .mm говорит компилятору, что этот файл должен быть скомпилирован как C++ для того, чтобы иметь доступ к другому C++ файлу. Переименовываем, запускаем и вуаля.  С++ метод вызовет printf и мы увидим в консоли результат выполнения поиска “perform search in cpp for TEMPLATE in PATH”.

Отлично. Теперь, нам надо передать результаты поиска из C++ назад в Objective-C. Как это сделать?

Для нашего SearchManager создаем еще один заголовочный класс – SearchManager-C-Interface.h – это С интерфейс

Objective-C и С++ в Xcode

в котором объявляем метод fileFound, который будет объявлен в Objective-C классе SearchManger и будет вызываться из C++

SearchManager-C-Interface.h

SearchManager.mm

И немного изменим наш С++ метод  performCppSearch

cppsearch.cpp

Запускаем и видим как наш Objective-C SearchManager успешно вызывает C++ performSearch, а в ответ C++ performSearch успешно вызывает Objective-C fileFound. В консоли мы увидим:

“perform search in cpp for TEMPLATE in PATH
file found with name FoundFileName and path FoundFilePath”

Отлично осталось одно но. Дело в том, что метод результатов fileFound – это С метод и нам из него желательно нужно вернуться с результатами в Objective-C. Проблема в том, что в методах C у нас нет указателя на self по умолчанию, как у нас есть в Objective-C методах, поэтому мы не можем из C метода сделать что-то вроде

[self fileFoundObjCWithFile:fileStr andPath:pathStr]; 

Вместо этого мы вызываем

[[SearchManager sharedManager] fileFoundObjCWithFile:fileStr andPath:pathStr];

Итоговый SearchManager.h

Итоговый SearchManager.mm
Вот и все! Данный рабочий проект вы можете посмотреть на GitHub. Желаю удачи!

github

Для наглядности вся схема выглядит так:

owerview-m

overview-h