要在C程序中使用的C ++ DLL

我有一个DLL的源代码是用C ++编写的。 我想创建该库的静态版本,我希望能够在另一个用纯C编写的库中链接这个静态库。编译器是Windows上的MinGW。 我应该如何编译第一个C ++静态库,以便它可以被C库使用?

如果您打算调用C ++类实例的成员函数,则需要提供转发函数。 您还需要提供至少一个函数来返回指向要访问的类实例的指针。 这有很重要的原因。 1)构造函数是特殊的, 没有名称,因此不能直接调用它们; 2)成员函数采用隐式的参数, this参数可以在堆栈寄存器中传递。

例如,假设您有一个名为SomeClass的类

 #include  class SomeClass { public: void Print(int value) { std::cout << value << std::endl; } void Print(const char *value) { std::cout << value << std::endl; } }; 

现在,您希望添加一种类型安全的方法来创建和访问该类的实例。 您可以创建一个提供创建function和转发function的C接口。 您可以首先添加一个额外的头文件,为SomeClass提供C接口

XSomeClass.h

 #ifdef __cplusplus extern "C" { #endif // C type representing SomeClass. This adds some type safety to it's use in C typedef struct XSomeClass XSomeClass; // This will create an instance of SomeClass and return a pointer to XSomeClass XSomeClass* SomeClass_Create( ); // forwarding calls to access member functions of SomeClass. These calls take // an explicit pointer to XSomeClass as the first parameter. self points to // an instance of SomeClass returned by SomeClass_Create() void SomeClass_PrintInt(XSomeClass* self, int value); void SomeClass_PrintString(XSomeClass* self, const char *value); #ifdef __cplusplus } #endif 

现在您需要提供C接口的实现。 这是允许您从C调用C ++成员函数的所有魔术发生的地方。

XSomeClass.cpp

 extern "C" XSomeClass* SomeClass_Create() { return reinterpret_cast(new SomeClass()); } extern "C" void SomeClass_PrintInt(XSomeClass* self, int value) { reinterpret_cast(self)->Print(value); } extern "C" void SomeClass_PrintString(XSomeClass* self, const char *value) { reinterpret_cast(self)->Print(value); } 

我建议使用reinterpret_cast不是C样式转换来防止意外删除const限定符。

要从C访问C ++库,您现在可以执行类似下面的示例

main.c中

 #include "XSomeClass.h" int main(int, char**) { XSomeClass *sc = SomeClass_Create(); SomeClass_PrintInt(sc, 1); SomeClass_PrintString(sc, "hello"); } 

注意:简单地将C ++库放在DLL中并为自由函数和静态成员函数调用GetProcAddress将很困难,因为您需要考虑名称修改 。

你没有,你做的恰恰相反。 您可以使C库在C ++程序中运行。 C ++包含C,而不是相反(超集C ++,子集C)。 所以,你可以编写一个C ++程序(使用C ++或C语法),并使用c ++编译器编译该程序。 然后,您可以使用C和C ++库。

您将C API添加到C ++库中。 在您添加的头文件中

 #ifdef __cplusplus extern "C" { #endif . . . #ifdef __cplusplus } #endif 

你在C api C ++文件中也这样做“但是你#ifdef因为你知道你将使用你的C ++编译器编译它们。

然后,您可以访问C ++ API文件,但是您的库可以保证使用C风格的应用程序二进制接口导出(无名称修改)。 然后可以从C应用程序中使用该库。

头文件在C和C ++项目中都很好用