【问题标题】:extern "C" with class and DLL带有类和 DLL 的外部“C”
【发布时间】: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相关):

  1. 由于class 不是C 语言,这是否相当于a struct?
  2. 构造函数是否有效?
  3. 虚拟析构函数是否有效(因为 C 没有 virtual)?
  4. bool 是如何处理的?
  5. static 在类的 extern "C" 中如何处理?
  6. private 数据在 extern "C" 块内是如何处理的?
  7. 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


【解决方案1】:

它不会将代码更改为 C。它不会导致 C++ 名称重整 - 例如,您不能在该块内重载暴露为 extern "C" 的函数,但代码仍然是 C++。

您只是被限制做不能从 C 调用的事情(在 extern "C" 块中)。您正在公开 C API,但您仍然可以在幕后使用 C++。只是不在你的extern "C" 界面的一部分

这也意味着您不能将成员函数(virtual 或不)导出为 extern "C",因为 C 没有这样的东西。

【讨论】:

  • @Peter 希望我的编辑能更清楚地说明这一点。
  • 每当出现这种情况时,我有点过于技术性的评论是 extern "C" 不会关闭名称修改;它指定使用 C 编译器的名称修饰,通常在函数名称前加上下划线。
  • @Peter 好的, 倾向于将其简单地认为是“导致此代码可以使用 C 调用约定进行调用(包括执行任何/无名称修改,这将是兼容 C)"。无论如何,我认为我们同意并且只是在挑剔(在这一点上)对帮助 OP 没有多大帮助的细节 - 或者?
  • 这就是为什么我说它是“超技术”的。
  • virtual 概念是否被忽略,析构函数是否考虑非特殊函数?
猜你喜欢
  • 1970-01-01
  • 2016-05-19
  • 2013-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-17
  • 2011-03-10
  • 1970-01-01
相关资源
最近更新 更多