Использование статических библиотек C / C ++ из приложений iPhone ObjectiveC - PullRequest
29 голосов
/ 18 декабря 2008

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

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

Я создал проект XCode, используя шаблон «статической библиотеки» Max OS X, и скопировал исходный код, а также написал программу-обработчик C (для обработки исключений), используя (extern «C»).

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

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

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

Просто потому, что C ++ используется внутри библиотеки, означает ли это, что внешне он все еще должен рассматриваться как программа C ++. Нет ли в любом случае для обеспечения этой абстракции?

Редактировать: Спасибо за ответы,

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

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

Ответы [ 4 ]

34 голосов
/ 18 декабря 2008

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

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

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!
$

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

2 голосов
/ 18 декабря 2008

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

РЕДАКТИРОВАТЬ: И скомпилировать его как исходный файл C ++, C не имеет понятия языковой связи. Есть пара других проблем с языковой связью (например, тот факт, что все функции extern "C" с одинаковыми именами являются одинаковыми, независимо от пространства имен).

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

1 голос
/ 19 сентября 2009

спасибо, за такую ​​хорошую дискуссию.

что я сделал:

1) Я создал статическую библиотеку, используя параметр статической библиотеки Cocaotouch. В этом у меня есть c / c ++ / obj-c все смешать. тем не менее, мой экспорт только классы obj-c. Фактически я использовал objc- to C ++.

2) Затем я создал приложение для iphone в программе X-code. Я добавил другие ссылки, помечающие мое имя библиотеки (-lxyz) // мое имя библиотеки libxyz.a Я добавил путь поиска lib, путь поиска заголовка

3) тогда я скомпилировал. Я получил ошибки. оператор operator новый, оператор удаления не найден.

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

4) потом строю заново ...

Вот и все.

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

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

ребята, вы можете поделиться.

1 голос
/ 18 декабря 2008

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

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

Что вы хотите сделать, так это заставить компилятор генерировать функции C с именами, не являющимися mangles, и с использованием C ABI.

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

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

Любимый способ настроить файл заголовка, чтобы один и тот же файл мог быть включен из исходных файлов 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 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...