Использование библиотеки C++ в коде C

У меня есть библиотека C++, которая предоставляет различные классы для управления данными. У меня есть исходный код библиотеки.

Я хочу расширить C++ API для поддержки вызовов функций C, чтобы библиотеку можно было использовать с кодом C и кодом C++ одновременно.

Я использую цепочку инструментов GNU (gcc, glibc и т. д.), поэтому поддержка языка и архитектуры не является проблемой.

Есть ли причины, по которым это технически невозможно?

Есть ли какие-то подводные камни, на которые мне нужно обратить внимание?

Имеются ли ресурсы, примеры кода и/или документация по этому поводу?


Некоторые другие вещи, которые я узнал:

  1. Используйте следующее, чтобы обернуть заголовки C++, которые должны использоваться кодом C.

#ifdef __cplusplus
extern "C" {  
#endif  
//  
// Code goes here ...  
//  
#ifdef __cplusplus  
} // extern "C"  
#endif
  1. Храните «настоящие» интерфейсы C++ в отдельных файлах заголовков, которые не включены в C. Вспомните здесь принцип PIMPL. . Использование #ifndef __cplusplus #error материала помогает обнаружить любое сумасшествие.
  2. Будьте осторожны с идентификаторами C++ в качестве имен в коде C
  3. Перечисления различаются по размеру в компиляторах C и C++. Вероятно, это не проблема, если вы используете цепочку инструментов GNU, но все же будьте осторожны.
  4. For structs follow the following form so that C does not get confused.

    typedef struct X { ... } X
    
  5. Затем используйте указатели для передачи объектов C++, их просто нужно объявить в C как структуру X, где X — объект C++.

Все это любезно предоставлено другом, который является волшебником C++.


person Community    schedule 13.10.2008    source источник
comment
Несколько поздно, но я написал небольшое руководство по C-оболочке для C++: teddy.ch/c++ _library_in_c   -  person Teddy    schedule 20.07.2015


Ответы (4)


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

extern "C" int foo(char *bar)
{
    return realFoo(std::string(bar));
}

Затем вы вызовете foo() из своего C-модуля, который передаст вызов функции realFoo(), реализованной на C++.

Если вам нужно предоставить полный класс C++ с элементами данных и методами, вам может потребоваться выполнить больше работы, чем этот пример простой функции.

person Greg Hewgill    schedule 13.10.2008
comment
Следует ли размещать extern "C" только в объявлениях (а не в определениях)? Поскольку вы упомянули слой, который объявляет функции, но ваш пример кода также является определением. Другими словами, должны ли мы поместить его в файлы заголовков или исходные файлы? (или в оба?) - person kyriakosSt; 15.10.2017
comment
@KyrSt: Если у вас есть заголовочный файл с объявлением функции, вы должны по крайней мере поставить туда extern "C". Ваш компилятор сообщит вам, если вам также нужно поместить его в определение. - person Greg Hewgill; 16.10.2017

C++ FAQ Lite: "Как смешивать код C и C++".

Некоторые ошибки описаны в ответах на эти вопросы:

  • [32.8] Как я могу передать объект класса C++ в/из функции C?
  • [32.9] Может ли моя функция C напрямую обращаться к данным в объекте класса C++?
person Alex B    schedule 13.10.2008

Основная проблема: исключения не могут быть перехвачены в C. Если существует возможность возникновения исключения в коде C++, очень тщательно пишите код C или обертки C++. И наоборот, механизмы, подобные исключениям (например, longjump) в коде C (которые встречаются в различных языках сценариев), не требуются для вызова деструкторов для объектов C++ в стеке.

person ejgottl    schedule 13.10.2008
comment
Отличный момент о звонках с длинным прыжком. Хотя я не использую их напрямую, используемые мной среды тестирования реализуют их. Что-то, что нужно иметь в виду. Спасибо - person Misha M; 14.10.2008

вы можете смешивать код C/C++. Если ваша функция main() находится в C++, вам просто нужно убедиться, что ваши функции c объявлены

extern "C"

Если ваш основной язык C, то, вероятно, все в порядке, за исключением статических переменных. Предполагается, что любые конструкторы с вашими статическими переменными должны вызываться до запуска main(). Этого не произойдет, если C является вашим основным. Если у вас много статических переменных, лучше всего заменить статические переменные на синглтоны.

person David Nehme    schedule 13.10.2008