您可以使用不透明指针创建 C 接口,由于所涉及的编译器的类型和版本不同,因此在您的情况下需要这样做。请注意,您可能不接受或返回非 C 类型,除非您还将它们包装在不透明的指针中。这并不难,但您需要做一些工作。
假设一个类“YourClass”,您将创建一个包含您的 C++ 类代码的 YourClassImpl.h 和 YourClassImpl.cpp(如果需要)。
YourClassImpl.h
class YourClass
{
private:
int value = 12345;
public:
YourClass() {}
~YourClass() {}
int getThing() { return value; }
void setThing(int newValue) { v = newValue}
};
然后,您将创建一个 YourClass.h,它是您的 C 头文件(由您的 DLL 的用户包含),其中包含一个不透明的指针 typedef 和您的 C 样式接口的声明。
YourClass.h
#ifdef MAKEDLL
# define EXPORT __declspec(dllexport) __cdecl
#else
# define EXPORT __declspec(dllimport) __cdecl
#endif
extern "C"
{
typedef struct YourClass *YC_HANDLE;
EXPORT YC_HANDLE CreateYourClass();
EXPORT void DestroyYourClass(YC_HANDLE h);
EXPORT int YourClassGetThing(YC_HANDLE h);
EXPORT void YourClassSetThing(YC_HANDLE h, int v);
}
您将在 YourClass.cpp 中定义这些函数。
YourClass.cpp
#include "YourClass.h"
#include "YourClassImpl.h"
extern "C"
{
EXPORT YC_HANDLE CreateYourClass()
{
return new YourClass{};
}
EXPORT void DestroyYourClass(YC_HANDLE h)
{
delete h;
}
EXPORT int YourClassGetThing(YC_HANDLE h)
{
return h->getThing();
}
EXPORT void YourClassSetThing(YC_HANDLE h, int v)
{
h->setThing(v);
}
}
在您的用户代码中,它们将包含 YourClass.h。
他们的代码.cpp
#include "YourClass.h"
int ResetValue(int newValue)
{
YC_HANDLE h = CreateYourClass();
auto v = YourClassGetThing(h);
YourClassSetThing(h, newValue);
DestroyYourClass(h);
return v;
}
链接到您的 DLL 的最常用方法是使用 LoadLibrary/GetProcAddress - 我还建议将 .def 文件添加到您的项目中,以确保函数被命名为“很好”并且不难访问,因为任何名称装饰。
需要注意的一些问题:
- 只有标准的 C 基本类型可以通过接口来回传递。不要使用任何 C++ 特定类型或类。
- 您可以安全使用 POD 和 POD 阵列,但请注意任何包装或对齐问题。
- 异常不得跨越接口边界 - 捕获任何被抛出的东西并将其转换为返回码或等效代码。
- 确保在边界任一侧分配的内存在同一侧释放。