我会通过以下方式做到这一点:
(如果使用 MSVC,请忽略 GCC 编译命令)
假设我有一个名为AAA的 C++ 类,在文件aaa.h、aaa.cpp中定义,并且AAA类有一个名为sayHi(const char *name)的方法,我想为 C 代码启用该方法。
AAA级的C++代码——纯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++ 的常规编译此类。该代码“不知道”它将被 C 代码使用。使用命令:
g++ -fpic -shared aaa.cpp -o libaaa.so
现在,同样在 C++ 中,创建一个 C 连接器:
在文件aaa_c_connector.h、aaa_c_connector.cpp中定义它。此连接器将定义一个名为AAA_sayHi(cosnt char *name)的 C 函数,它将使用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 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
再次使用常规 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。为了引起注意