Подтвердить что ты не робот

Использование статических библиотек C/С++ из приложений iPhone ObjectiveC

Возможно ли иметь C статический библиотечный API, который использует С++ внутри и скрывает это от пользователей библиотеки?

У меня есть переносная библиотека С++, которую я хочу статически связывать с приложением iPhone.

Я создал проект Xcode с использованием шаблона статической библиотеки Max OS X и скопировал источник через, а также написал C wapper (для обработки исключений), используя (extern "C" ).

Я пытаюсь использовать сгенерированную библиотеку (файл .a) в другом приложении Cocoa iPhone.

Все работает хорошо, если я использую (.mm) расширения для вызывающего файла ObjectiveC и (.cpp) для класса реализации в библиотеке.

Но я получаю неразрешенные символы при связывании, когда я пытаюсь изменить файл-оболочку на расширение (.c), хотя все файлы файлы-оболочки являются только функциями C.

Просто потому, что С++ используется внутренне в библиотеке, означает ли это, что извне он все равно должен рассматриваться как программа на С++. Разве не в силах обеспечить эту абстракцию?

Изменить: Спасибо за ответы,

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

Казалось бы, я не могу, и я должен использовать (.mm) файлы в своих классах ObjectiveC.

4b9b3361

Ответ 1

Слишком сложно сделать это в комментариях, так что я просто собираюсь быстро продемонстрировать, что у вас есть проблемы с привязкой. Когда Xcode встречает файлы, он использует правила сборки на основе суффикса, чтобы решить, какой компилятор использовать. По умолчанию gcc связывает файлы со стандартной библиотекой C, но не связывается со стандартной библиотекой С++. Архивные файлы (статические библиотеки) не имеют никакого разрешения на соединение вообще. Они в основном представляют собой архив объектных файлов, которые необходимо связать. Поскольку в вашем проекте нет файлов .mm или .cpp, g++ никогда не вызывается, и ваши файлы никогда не связаны со стандартными библиотеками. Чтобы исправить это, просто добавьте стандартные библиотеки С++ к другим флагам компоновщика в проекте Xcode или просто добавьте их в предварительно определенный параметр других флагов в виде -l (например, -lstdС++).

Вот быстрая демонстрация:

stw.h:

#ifdef __cplusplus
extern "C"
#endif
void show_the_world(void);

stw.cpp:

#include <iostream>
#include "stw.h"
using namespace std;

extern "C" void show_the_world() {
  cout << "Hello, world!\n";
}

Постройте библиотеку:

$ g++ -c stw.cpp -o stw.cpp -O0 -g
$ ar rcs stw.a stw.o

Использование библиотеки из приложения C:

myapp.c:

#include "stw.h"

int main() {
  show_the_world();
  return 0;
}

Построение приложения C:

$ gcc -o myapp myapp.c stw.a -lstdc++ -g -O0
$ ./myapp
Hello, world!
$

Если вы попытаетесь скомпилировать без -lstdС++, вы получите все нерешенные проблемы, потому что у компилятора C абсолютно нет идеи, что он должен ссылаться на среду выполнения С++ (и почему бы это сделать, правильно??!?), чтобы вы чтобы добавить это вручную. Другой вариант, который у вас есть, - изменить правило сборки для вашего проекта... вместо того, чтобы Xcode использовать gcc для сборки файлов .c и .m, скажите ему использовать g++, и ваши проблемы будут решены.

Ответ 2

Вы должны объявить функции, которые должны быть видимыми extern "C". Их подписи должны быть C-совместимыми, но содержимое не имеет (например, вы можете обращаться к объектам С++, но вы не можете передавать их напрямую, указатели в порядке). Затем символы будут видны в любой C-совместимой среде.

EDIT: и скомпилируйте его как исходный файл С++, C не имеет понятия языковой привязки. Есть еще пара gotchas с языковой связью (например, тот факт, что все extern "C" функции с тем же именем являются одной и той же функцией, независимо от пространства имен).

EDIT2: В заголовке вы можете проверить макрос __cplusplus и использовать его для установки на С++ и других языках соответственно (потому что С++ потребует объявлений extern "C", а на других языках, вероятно, будут жаловаться на них).

Ответ 3

В основном, когда вы скомпилируете C-функции с помощью компилятора С++, он управляет именами функций и использует С++ ABI.

Когда вы используете расширение *.cpp или *.mm, вы используете компилятор С++.

То, что вы хотите сделать, - заставить компилятор генерировать функции C с именами un-mangles и использовать C ABI.

Вы можете сделать это с помощью:

  • Скомпилировать с компилятором C.
  • Компиляция с компилятором С++, но убедитесь, что вы префикс объявления функций с помощью extern "C"

Любимый способ настроить файл заголовка, чтобы один и тот же файл мог быть включен как из исходных файлов C, так и С++:

#ifndef HEADER_GUARD_1_H
#define HEADER_GUARD_1_H

#ifdef __cplusplus
extern "C" {
#endif

// Declare C function interface here.
int myFunc(int x,char*);

#ifdef __cplusplus
}
#endif

#endif 

Ответ 4

спасибо за такое хорошее обсуждение.

что я сделал:

1) Я создал статический lib, используя опцию cocaotouch static lib. В том, что у меня есть c/С++/obj-c all mix. однако мой экспорт - это только классы obj-c.  Infact я использовал objc- to c на С++.

2), то я создал iphone-приложение в X-коде proj. Я добавил флагов другой ссылки my lib name (-lxyz)//имя моего lib - libxyz.a Я добавил путь поиска lib, путь поиска заголовка

3), то я скомпилировал. У меня появились ошибки.  говоря oeprator new, оператор delete не найден.

3), то кроме моего appdelegate, контроллера просмотра, я добавил    dummy cpp (.h,.cpp)... atestdummy.h atestdummy.cpp

4), то я снова построю...

что это сработало.

Итак - я, независимо от того, какие предложения они дали раньше, работал у меня. основная причина, если только приложение u не видит файл .cpp.mm с кодом cpp, связанный не будет использовать g++.

Спасибо всем. Я прочитал выше и решил мою проблему.

u ребята хорошо поделиться.