Я бы сделал это следующим образом:
(При работе с MSVC игнорируйте команды компиляции GCC)
Предположим, у меня есть класс C ++ с именем AAA , определенный в файлах aaa.h, aaa.cpp , и что класс AAA имеет метод с именем sayHi (const char * name) , который я хочу включить для кода 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
// 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
EDIT:
В некоторых дистрибутивах linux -laaa
и -lstdc++
могут также потребоваться для последней команды компиляции. Благодаря @AlaaM. за внимание