Я б зробив це наступним чином:
(Якщо ви працюєте з MSVC, ігноруйте команди компіляції GCC)
Припустимо, що у мене є клас C ++ з іменем AAA , визначений у файлах aaa.h, aaa.cpp , і що клас AAA має метод sayHi ( ім'я const char *) , який я хочу включити для коду C.
Код C ++ класу AAA - чистий C ++, я його не модифікую:
aaa.h
#ifndef AAA_H
#define AAA_H
class AAA {
public:
AAA();
void sayHi(const char *name);
};
#endif
aaa.cpp
#include <iostream>
#include "aaa.h"
AAA::AAA() {
}
void AAA::sayHi(const char *name) {
std::cout << "Hi " << name << std::endl;
}
Компіляція цього класу, як це регулярно робиться для С ++. Цей код "не знає", що він буде використовуватися кодом 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 <cstdlib>
#include "aaa_c_connector.h"
#include "aaa.h"
#ifdef __cplusplus
extern "C" {
#endif
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 *) . Тепер я можу створити основний файл 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. за увагу