在这里帮助我,因为我确信我不能做我想做的事情,并且有一半确信应该有一个合适的解决方法。
我有一个用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
是否正确且可接受?
这里真的很难找到一个“干净”的答案。
答案 0 :(得分:4)
MSDN上有几篇关于混合C和C ++的文章:
http://msdn.microsoft.com/en-us/library/aa270933%28v=vs.60%29.aspx
http://msdn.microsoft.com/en-us/library/s6y4zxec%28v=vs.60%29.aspx
我认为你可以简单地看一下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”声明之外。
看看这里:
答案 1 :(得分:1)
答案在你的问题中,如果没有定义__cplusplus那么你不希望编译器看到C ++声明:
#ifdef __cplusplus
// C++ declarations here
#endif
将它全部放在一个.lib文件中有点棘手,你无法链接DLL。但是,您可以运行lib.exe来合并C和C ++项目的导入库。从来没有尝试过,但它应该工作。将单个项目中的C和C ++源代码文件混合并生成单个DLL肯定会起作用。这可能是您应该追求的,您的客户端将被单个.lib所困扰,需要部署两个DLL。还有一个提示,你可能不应该首先这样做。
答案 2 :(得分:-1)
您可以使用一个标题或多个标题,这无关紧要。但是你必须将所有C ++内容导出为C ++内容,并将所有C内容导出为C内容。不要像汉斯推荐的那样混合 - 它无论如何都不会起作用。
列出所有C函数并将它们放在“C”边界,一个单独的标题中,或者只放在一个标题中。如果要将C和C ++放在标题中,只需使用__cplusplus
符号控制编译(对于客户端)。