如果您计划调用C++类实例的成员函数,则需要提供转发函数.您还需要提供至少一个函数来返回指向要访问的类实例的指针.这有很重要的原因.1)构造函数是特殊的,没有名称,因此不能直接调用它们; 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; }
};
Run Code Online (Sandbox Code Playgroud)
现在,您想要添加一种类型安全的方法来创建和访问该类的实例.您可以创建一个提供创建功能和转发功能的C接口.您可以首先添加一个额外的头文件来提供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
Run Code Online (Sandbox Code Playgroud)
现在您需要提供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);
}
Run Code Online (Sandbox Code Playgroud)
我建议使用reinterpret_castC风格的强制转换来防止意外删除const限定符.
要从C访问C++库,您现在可以执行类似下面的示例
main.c中
#include "XSomeClass.h"
int main(int, char**)
{
XSomeClass *sc = SomeClass_Create();
SomeClass_PrintInt(sc, 1);
SomeClass_PrintString(sc, "hello");
}
Run Code Online (Sandbox Code Playgroud)
注意:简单地将C++库放在DLL中并调用GetProcAddress自由函数和静态成员函数将很困难,因为您需要考虑名称修改.