【发布时间】:2023-04-04 21:17:01
【问题描述】:
我收到了一个使用 extern "C" 的 C++ DLL 源代码:
extern "C"
{
class Something
{
public:
__declspec(dllexport) Something();
__declspec(dllexport) virtual ~Something();
__declspec(dllexport) bool function_one(const char * some_text);
static __declspec(dllexport) char * get_version();
private:
unsigned int m_data;
};
}
C++ 程序正在调用 DLL。 仅供参考,在 Windows 7 平台上使用 Visual Studio 2017。
问题 *(均与extern "C"和class相关):
- 由于
class不是C 语言,这是否相当于astruct? - 构造函数是否有效?
- 虚拟析构函数是否有效(因为 C 没有
virtual)? -
bool是如何处理的? -
static在类的extern "C"中如何处理? -
private数据在extern "C"块内是如何处理的? -
noexcept如何在extern "C"块中处理 构造函数?
Visual Studio 2017 编译器不会使用上述代码生成任何错误或警告。
VS2017代码分析器只对构造函数产生警告:
C26439 This kind of function may not throw. Declare it 'noexcept' (f.6).
研究:
StackOverflow上与此问题相关的问题提到了我上面列出的“extern“C”has the effect of resolving name mangling. However, they don't address the issues ofvirtual,bool`、私有数据等。
此外,许多与 DLL 相关的答案建议不要使用非 POD 结构,因为编译器之间的布局可能会发生变化(包括相同版本的编译器);例如,字符数组优于std::string。
【问题讨论】:
-
extern "C"并不意味着“将此代码编译为 C 代码”。它的意思是“生成可以从 C 代码调用的编译代码”。这主要是关于外部名称和调用约定,它强烈关于 C 编译器和 C++ 编译器之间的交互。 -
这个源代码有异味。首先,可以在类上使用
__declspec(dllexport)而不是单个成员,这非常冗长。其次,declspec 几乎总是隐藏在一个宏中,该宏扩展为导出或导入变体,具体取决于正在编译的内容。第三,extern "C"对类成员没有多大意义,因此被忽略。 -
我很困惑。 C语言没有虚析构函数的概念,那如何从C代码中调用呢?
-
@n.m.是的,有很多源代码的味道;这就是我在这里发帖的原因。给我的源代码很混乱,比如有一个
private访问说明符。 -
不能从C代码调用成员函数,这就是
extern "C"不适用于它们的原因。
标签: c++ visual-studio class dll extern