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

标签 c++ c dll mingw

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

最佳答案

如果您计划调用 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; }
};

现在,您想要添加一种类型安全的方法来创建和访问该类的实例。您可以创建一个提供创建功能和转发功能的C接口(interface)。您可以从添加额外的头文件开始,为 SomeClass

提供 C 接口(interface)

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 接口(interface)的实现。这就是允许您从 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 将很困难,因为您需要考虑帐号name mangling .

关于在 C 程序中使用的 C++ DLL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17575060/

相关文章:

c - 读取 double 据类型后无法读取字符串

c++ - 计算文件中每个字母的出现次数?

c++ - Delphi与C++dll通信(参数)

c++ - Boost::graph 获取到根的路径

c++ - 如何使用前向声明类的成员函数?

c++ - 将控制字符传递给 char 数组

c++ - 嵌套类的值初始化

无法将参数 1 从 'const char *' 转换为 'LPCWSTR'

c++ - 如何将 C++ dll 项目添加到 Visual Basic 引用中?

c# - DLL 和内存不足异常