我可以在单个DLL头中混合使用C和C ++导出吗?

时间:2013-04-05 08:30:51

标签: windows visual-c++ dll

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

我有一个用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是否正确且可接受?

这里真的很难找到一个“干净”的答案。

3 个答案:

答案 0 :(得分: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

答案 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符号控制编译(对于客户端)。