Lo haría de la siguiente manera:
(Si trabaja con MSVC, ignore los comandos de compilación de GCC)
Supongamos que tengo una clase C ++ llamada AAA , definida en los archivos aaa.h, aaa.cpp , y que la clase AAA tiene un método llamado sayHi (const char * name) , que quiero habilitar para el código C.
El código C ++ de la clase AAA - Pure C ++, no lo modifico:
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;
}
Compilar esta clase como se hace habitualmente para C ++. Este código "no sabe" que va a ser utilizado por el código C. Usando el comando:
g++ -fpic -shared aaa.cpp -o libaaa.so
Ahora, también en C ++, creando un conector C. Definiéndolo en archivos aaa_c_connector.h, aaa_c_connector.cpp . Este conector va a definir una función C, llamada AAA_sayHi (cosnt char * name) , que usará una instancia de AAA y llamará a su método:
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
Compilarlo, nuevamente, usando un comando de compilación normal de C ++:
g++ -fpic -shared aaa_c_connector.cpp -L. -laaa -o libaaa_c_connector.so
Ahora tengo una biblioteca compartida (libaaa_c_connector.so), que implementa la función C AAA_sayHi (const char * name) . Ahora puedo crear un archivo principal en C y compilarlo todo junto:
main.c
#include "aaa_c_connector.h"
int main() {
AAA_sayHi("David");
AAA_sayHi("James");
return 0;
}
Compilarlo usando un comando de compilación de C:
gcc main.c -L. -laaa_c_connector -o c_aaa
Necesitaré configurar LD_LIBRARY_PATH para que contenga $ PWD, y si ejecuto el ejecutable ./c_aaa , obtendré el resultado que espero:
Hi David
Hi James
EDITAR:
En algunas distribuciones de Linux, -laaa
y -lstdc++
también puede ser necesario para el último comando de compilación. Gracias a @AlaaM. para la atención