Je procéderais de la manière suivante :
(Si vous travaillez avec MSVC, ignorez les commandes de compilation de GCC)
Supposons que j'aie une classe C++ nommée AAA définis dans les fichiers aaa.h, aaa.cpp et que la classe AAA possède une méthode nommée sayHi(const char *nom) que je souhaite activer pour le code C.
Le code C++ de la classe AAA - C++ pur, je ne le modifie pas :
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;
}
Compiler cette classe comme on le fait régulièrement pour le C++. Ce code "ne sait pas" qu'il va être utilisé par du code C. En utilisant la commande :
g++ -fpic -shared aaa.cpp -o libaaa.so
Maintenant, toujours en C++, création d'un connecteur C :
Le définir dans les fichiers aaa_c_connector.h, aaa_c_connector.cpp . Ce connecteur va définir une fonction C, nommée AAA_sayHi(cosnt char *nom) qui utilisera une instance de AAA et appellera sa méthode :
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 implement functions in C++, which will externally
// appear as C functions (which means that the function IDs will be their names, unlike
// the regular C++ behavior, which allows defining multiple functions with the same name
// (overloading) and hence uses function signature hashing to enforce unique IDs),
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
Le compiler, encore une fois, en utilisant une commande de compilation C++ normale :
g++ -fpic -shared aaa_c_connector.cpp -L. -laaa -o libaaa_c_connector.so
J'ai maintenant une bibliothèque partagée (libaaa_c_connector.so), qui implémente la fonction C AAA_sayHi(const char *nom) . Je peux maintenant créer un fichier principal en C et compiler le tout :
main.c
#include "aaa_c_connector.h"
int main() {
AAA_sayHi("David");
AAA_sayHi("James");
return 0;
}
Compilation à l'aide d'une commande de compilation C :
gcc main.c -L. -laaa_c_connector -o c_aaa
Je devrai définir LD_LIBRARY_PATH pour qu'il contienne $PWD, et si je lance l'exécutable ./c_aaa J'obtiendrai le résultat escompté :
Hi David
Hi James
EDIT :
Sur certaines distributions Linux, -laaa
et -lstdc++
peut également être nécessaire pour la dernière commande de compilation. Merci à @AlaaM. pour son attention.