我有一个dll,其源代码是用C ++编写的。我想创建该库的静态版本,我希望能够将这个静态库链接到另一个用纯C编写的库中。编译器是Windows上的MinGW。 我应该如何编译第一个C ++静态库,以便它可以被C库使用?
答案 0 :(得分:5)
如果您计划调用C ++类实例的成员函数,则需要提供转发函数。您还需要提供至少一个函数来返回指向要访问的类实例的指针。这有很重要的原因。 1)构造函数是特殊的,并且 not 具有名称,因此无法直接调用它们; 2)成员函数采用隐式this
参数,该参数可以在堆栈上传递或在寄存器中。
例如,假设您有一个名为SomeClass
#include <iostream>
class SomeClass
{
public:
void Print(int value) { std::cout << value << std::endl; }
void Print(const char *value) { std::cout << value << std::endl; }
};
现在,您要添加一种类型安全的方法来创建和访问该类的实例。您可以创建一个提供创建功能和转发功能的C接口。您可以首先添加一个额外的头文件,以便为SomeClass
<强> 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<XSomeClass*>(new SomeClass());
}
extern "C" void SomeClass_PrintInt(XSomeClass* self, int value)
{
reinterpret_cast<SomeClass*>(self)->Print(value);
}
extern "C" void SomeClass_PrintString(XSomeClass* self, const char *value)
{
reinterpret_cast<SomeClass*>(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
将很困难,因为您需要考虑{{ 3}} 子>
答案 1 :(得分:2)
你没有,你反其道而行之。您可以使C库在C ++程序中运行。 C ++包含C,而不是相反(超集C ++,子集C)。所以,你可以编写一个C ++程序(使用C ++或C语法),并使用c ++编译器编译该程序。然后,您可以使用C和C ++库。
答案 2 :(得分:2)
您将C API添加到C ++库中。在头文件中添加
#ifdef __cplusplus
extern "C" {
#endif
.
.
.
#ifdef __cplusplus
}
#endif
您在C api C ++文件中也这样做“但是您可以省略#ifdef
,因为您知道将使用C ++编译器编译它们。
您可以使用C ++ C ++文件访问C ++ API,但保证您的库使用C样式应用程序二进制接口(无名称修改)导出。然后可以从C应用程序中使用该库。
头文件适合在C和C ++项目中使用