Tôi sẽ làm điều đó theo cách sau:
(Nếu làm việc với MSVC, hãy bỏ qua các lệnh biên dịch GCC)
Giả sử rằng tôi có một lớp C ++ có tên AAA , được định nghĩa trong các tệp aaa.h, aaa.cpp và lớp AAA có một phương thức có tên sayHi (const char * name) mà tôi muốn bật cho mã C.
Mã C ++ của lớp AAA - C ++ thuần túy, tôi không sửa đổi nó:
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;
}
Biên dịch lớp này như thường xuyên được thực hiện cho C ++. Mã này "không biết" rằng nó sẽ được sử dụng bởi mã C. Sử dụng lệnh:
g++ -fpic -shared aaa.cpp -o libaaa.so
Bây giờ, cũng trong C ++, tạo một trình kết nối C. Định nghĩa nó trong các tệp aaa_c_connector.h, aaa_c_connector.cpp . Trình kết nối này sẽ xác định một hàm C, có tên AAA_sayHi (cosnt char * name) , sẽ sử dụng một thể hiện của AAA và sẽ gọi phương thức của nó:
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
Biên dịch nó, một lần nữa, sử dụng lệnh biên dịch C ++ thông thường:
g++ -fpic -shared aaa_c_connector.cpp -L. -laaa -o libaaa_c_connector.so
Bây giờ tôi có một thư viện được chia sẻ (libaaa_c_connector.so), thực hiện hàm C AAA_sayHi (const char * name) . Bây giờ tôi có thể tạo một tệp C chính và biên dịch tất cả lại với nhau:
main.c
#include "aaa_c_connector.h"
int main() {
AAA_sayHi("David");
AAA_sayHi("James");
return 0;
}
Biên dịch nó bằng lệnh biên dịch C:
gcc main.c -L. -laaa_c_connector -o c_aaa
Tôi sẽ cần đặt LD_LIBRARY_PATH để chứa $ PWD và nếu tôi chạy tệp thực thi ./c_aaa , tôi sẽ nhận được đầu ra mà tôi mong đợi:
Hi David
Hi James
BIÊN TẬP:
Trên một số bản phân phối linux, -laaa
và -lstdc++
cũng có thể được yêu cầu cho lệnh biên dịch cuối cùng. Cảm ơn @AlaaM. cho sự chú ý