2

在这里帮帮我,因为我半信半疑我不能做我想做的事,半信半疑应该有一个合适的解决方法。

我有一个用 C++ 实现的 DLL,因此将一些类导出到链接到它的其他 C++ 模块。没关系。现在我想从一个 C 模块(另一个 DLL)链接到这个 DLL,所以我将提供一个“扁平化”的 C 接口并在内部处理 C++ 的东西。那也没关系。

问题是我想将它作为单个 .h 和关联的 .lib 提供给 C 或 C++ 客户端。所以我的 DLL 中有类似于以下内容的内容:

#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

// export a class for the C++ clients
class DLL_API CExportedClass 
{
public:
    CExportedClass(); 
    // etc. etc.
};

// export flattened C interface for non-C++ clients
#ifdef __cplusplus
extern "C" {
#endif

DLL_API void DoSomethingInternally(); // i.e. implementation uses CExportedClass

#ifdef __cplusplus
}
#endif

当然,这在导入 C++ 模块时可以正常工作,但在导入 C 模块时无法编译,因为它无法识别class声明。

所以我认为我什至可以做到这一点是错误的吗?我需要分成两个标题吗?在声明(或其他类型)#ifdef __cplusplus周围使用是否正确且可接受?class#ifdef

在这里真正为“干净”的答案而苦苦挣扎。

4

3 回答 3

4

MSDN上有几篇关于混合C和C++的文章:

我认为您可以简单地查看 windows.h 或类似的头文件,它们对 C 和 C++ 都适用,没有任何问题。

基本上这是它的工作原理:

在头文件的最开始

#ifndef _MYHEADER__H
#define _MYHEADER__H

#ifdef __cplusplus
extern "C" {
#endif 

//Decalrations
//........
//........


//Bottom of your header

#ifdef __cplusplus
}
#endif
#endif 

所以你的标题应该是这样的:

#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

#ifdef __cplusplus
//This part of header is not visible for ANSI C compiler
// export a class for the C++ clients
class DLL_API CExportedClass 
{
public:
    CExportedClass(); 
    // etc. etc.
};
#endif


#ifdef __cplusplus
extern "C" {
#endif 


DLL_API void DoSomethingInternally(); // i.e. implementation uses CExportedClass

#ifdef __cplusplus      
}
#endif

这是它寻找 ANSI C 编译器的方式:

#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
DLL_API void DoSomethingInternally(); 

这是它寻找 C++ 编译器的方式:

#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

class DLL_API CExportedClass 
{
public:
    CExportedClass(); 
    // etc. etc.
};
extern "C" {

    DLL_API void DoSomethingInternally();

}

但是,您在标头中声明类,因此 C 编译器不会对此感到满意,您应该将其放在“C”声明之外。

看看这里:

http://www.parashift.com/c++-faq/mixing-c-and-cpp.html

于 2013-04-05T08:36:46.903 回答
1

答案在您的问题中,如果 __cplusplus 未定义,那么您不希望编译器看到 C++ 声明:

#ifdef __cplusplus
// C++ declarations here
#endif

将它们全部放在一个 .lib 文件中有点棘手,您无法链接 DLL。但是,您可以运行 lib.exe 来合并 C 和 C++ 项目的导入库。从未真正尝试过,但它应该可以工作。肯定会起作用的是将 C 和 C++ 源代码文件混合在一个项目中并生成一个 DLL。这可能是您应该追求的,您的客户将被需要部署两个 DLL 的单个 .lib 所迷惑。还有一个提示,你可能一开始就不应该这样做。

于 2013-04-05T10:34:39.133 回答
-1

您可以使用一个标头或多个标头,这无关紧要。但是您必须将所有 C++ 内容导出为 C++ 内容,并将所有 C 内容导出为 C 内容。不要像 Hans 建议的那样混合——它无论如何都行不通。

列出所有 C 函数并将它们放在“C”边界、一个单独的标题或仅一个标题中。如果您将 C 和 C++ 放在头文件中,只需使用__cplusplus符号控制编译(对于客户端)。

于 2013-04-06T09:19:14.963 回答