Как вызвать функцию C ++ из C?

Я знаю это.

Вызов функции C из C ++:

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

//main.cpp extern "C" void C_library_function(int x, int y);//prototype C_library_function(2,4);// directly using it. 

Это не повлияет на имя C_library_function и линкер найдет то же имя в своих файлах ввода * .lib и проблема будет решена.

Вызов функции C ++ из C ???

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

Кстати, я использую MSVC

Вам необходимо создать API C для раскрытия функциональности вашего кода на C ++. В принципе, вам нужно будет написать код на C ++, который объявлен extern «C» и имеет чистый C API (например, не использует classы), который обертывает библиотеку C ++. Затем вы используете чистую библиотеку оболочек C, которую вы создали.

Ваш API-интерфейс может необязательно следовать объектно-ориентированному стилю, хотя C не является объектно-ориентированным. Пример:

  // *.h file // ... #ifdef __cplusplus #define EXTERNC extern "C" #else #define EXTERNC #endif typedef void* mylibrary_mytype_t; EXTERNC mylibrary_mytype_t mylibrary_mytype_init(); EXTERNC void mylibrary_mytype_destroy(mylibrary_mytype_t mytype); EXTERNC void mylibrary_mytype_doit(mylibrary_mytype_t self, int param); #undef EXTERNC // ... // *.cpp file mylibrary_mytype_t mylibrary_mytype_init() { return new MyType; } void mylibrary_mytype_destroy(mylibrary_mytype_t untyped_ptr) { MyType* typed_ptr = static_cast(untyped_ptr); delete typed_ptr; } void mylibrary_mytype_doit(mylibrary_mytype_t untyped_self, int param) { MyType* typed_self = static_cast(untyped_self); typed_self->doIt(param); } 

Я бы сделал это следующим образом:

(Если вы работаете с MSVC, игнорируйте команды компиляции GCC)

Предположим, что у меня есть class C ++ с именем AAA , определенный в файлах aaa.h, aaa.cpp , и что class AAA имеет метод с именем sayHi (const char * name) , который я хочу включить для кода C.

Код C ++ classа AAA – Pure C ++, я его не изменяю:

// aaa.h

 #ifndef AAA_H #define AAA_H class AAA { public: AAA(); void sayHi(const char *name); }; #endif 

// aaa.cpp

 #include  #include "aaa.h" AAA::AAA() { } void AAA::sayHi(const char *name) { std::cout << "Hi " << name << std::endl; } 

Компиляция этого classа, как обычно выполняется для C ++. Этот код «не знает», что он будет использоваться кодом C. Используя команду:

 g++ -fpic -shared aaa.cpp -o libaaa.so 

Теперь, также на C ++, создаем C-коннектор. Определив его в файлах aaa_c_connector.h, aaa_c_connector.cpp . Этот соединитель будет определять функцию C, названную AAA_sayHi (cosnt char * name) , которая будет использовать экземпляр AAA и вызовет его метод:

// aaa_c_connector.h

 #ifndef AAA_C_CONNECTOR_H #define AAA_C_CONNECTOR_H #ifdef __cplusplus extern "C" { #endif void AAA_sayHi(const char *name); #ifdef __cplusplus } #endif #endif 

// aaa_c_connector.cpp

 #include  #include "aaa_c_connector.h" #include "aaa.h" #ifdef __cplusplus extern "C" { #endif // Inside this "extern C" block, I can define C functions that are able to call C++ code static AAA *AAA_instance = NULL; void lazyAAA() { if (AAA_instance == NULL) { AAA_instance = new AAA(); } } void AAA_sayHi(const char *name) { lazyAAA(); AAA_instance->sayHi(name); } #ifdef __cplusplus } #endif 

Скомпилировав его, опять же, используя обычную команду компиляции C ++:

 g++ -fpic -shared aaa_c_connector.cpp -L. -laaa -o libaaa_c_connector.so 

Теперь у меня есть общая библиотека (libaaa_c_connector.so), которая реализует функцию C AAA_sayHi (const char * name) . Теперь я могу создать основной файл C и скомпилировать его все вместе:

// main.c

 #include "aaa_c_connector.h" int main() { AAA_sayHi("David"); AAA_sayHi("James"); return 0; } 

Компиляция с помощью команды компиляции C:

 gcc main.c -L. -laaa_c_connector -o c_aaa 

Мне нужно установить LD_LIBRARY_PATH, чтобы он содержал $ PWD, и если я запустил исполняемый файл ./c_aaa , я получу ожидаемый результат:

 Hi David Hi James 

РЕДАКТИРОВАТЬ:

В некоторых дистрибутивах linux для последней команды компиляции также могут потребоваться -laaa и -lstdc++ . Благодаря @AlaaM. за внимание

Предполагая, что C ++ API является C-совместимым (без classов, шаблонов и т. Д.), Вы можете обернуть его в extern "C" { ... } , точно так же, как вы это делали, идя другим путем.

Если вы хотите открыть объекты и другие симпатичные материалы C ++, вам придется написать API-интерфейс обертки.

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

экспортируйте свои C ++-функции в качестве extern «C» (например, символы стиля C) или используйте формат файла .def для определения неэкспорированных символов экспорта для C ++-компоновщика при создании библиотеки C ++, тогда C-компоновщик не должен иметь никаких проблем, читающих его

 #include  ////////////// // C++ code // ////////////// struct A { int i; int j; A() {i=1; j=2; std::cout << "class A created\n";} void dump() {std::cout << "class A dumped: " << i << ":" << j << std::endl;} ~A() {std::cout << "class A destroyed\n";} }; extern "C" { // this is the C code interface to the class A static void *createA (void) { // create a handle to the A class return (void *)(new A); } static void dumpA (void *thisPtr) { // call A->dump () if (thisPtr != NULL) // I'm an anal retentive programmer { A *classPtr = static_cast(thisPtr); classPtr->dump (); } } static void *deleteA (void *thisPtr) { // destroy the A class if (thisPtr != NULL) { delete (static_cast(thisPtr)); } } } //////////////////////////////////// // this can be compiled as C code // //////////////////////////////////// int main (int argc, char **argv) { void *handle = createA(); dumpA (handle); deleteA (handle); return 0; } 
  • Использование библиотеки c ++ в c #
  • В C ++ / CLI, что делает символ шляпы?
  • Двойное удаление в файле initializer_list vs 2013
  • Что именно «нарушено» с помощью двухфазного экземпляра шаблона Microsoft Visual C ++?
  • Как установить OpenCV 2.0 на win32
  • Ошибка LNK2005 в CLR Windows Form
  • Как открыть окно консоли в Visual C ++?
  • Как использовать WinDbg для анализа дампа сбоя для приложения VC ++?
  • Что такое Microsoft Visual Studio, эквивалентная опции GCC ld - whall-archive
  • Win32: Верните окно вверх
  • постоянные переменные, не работающие в заголовке
  • Давайте будем гением компьютера.