c++ - 如何定义C结构: c-linkage and udt

标签 c++ visual-c++

我用 C-ABI 接口(interface)用 X 语言编写了 dll。 我想在我的 C++ 程序中使用这个 C-ABI。

我在main.cpp中这样写:

extern "C" {
struct Foo {
  const char * const data;
  unsigned len;
};
struct Foo f(void);
}

int main()
{
}

并得到编译器的警告(visual c++/15.7.5/windows 7/32bit):

(7): warning C4190: 'f' has C-linkage specified, but returns UDT 'Foo' which is incompatible with C

(7): note: see declaration of 'Foo'

这里是神马链接:https://godbolt.org/g/ztx1kf

我读了Error in C++ code linkage: warning C4190: type has C-linkage specified, but returns UDT which is incompatible with C ,但就我而言,我没有“C++ 代码” 完全在我的 POD 结构中。

我如何让编译器相信这不是 C++ struct Foo,而是 C struct Foo

我尝试将它移动到单独的头文件 (.h),但这没有任何改变。

如果我将 const char * const data 替换为 const char * 警告消失, 我也不明白,但我不想更改结构的定义。

最佳答案

x64 calling convention docs说明 UDT 在 eax 中返回如果它们足够小并且符合某些标准:

To return a user-defined type by value in RAX, it must have a length of 1, 2, 4, 8, 16, 32, or 64 bits. It must also have no user-defined constructor, destructor, or copy assignment operator; no private or protected non-static data members; no non-static data members of reference type; no base classes; no virtual functions; and no data members that do not also meet these requirements.

同时 FooStandardLayout 类型(因此我们希望它可以工作),const非静态数据成员使复制赋值运算符被删除,这可能就是它们的意思,即使它说的是“用户定义”。顺便说一句,这使其成为非 TrivialType,因此不是 C++03 意义上的 POD。

它也超过了最大尺寸,但即使我们删除了len ,以上内容仍然会阻止它成为“POD”。

同样,x86 calling convention docs解释类似的东西:

[...] except for 8-byte structures, which are returned in the EDX:EAX register pair. Larger structures are returned in the EAX register as pointers to hidden return structures. [...] Structures that are not PODs will not be returned in registers.

例如,像下面这样的一个函数:

struct Foo
{ 
    const uint32_t x;
};

Foo f(void)
{
    Foo foo = { 12345 };
    return foo;
}

在 x86/x64 C++ 模式下编译时,Foo被认为是非 POD,因此 eax/rax包含文档引导我们期望的对象的地址。

但是,在 x86/x64 C 模式下编译时,Foo被认为是 POD(我们正在编译 C),因此您将获得 uint32_t直接在 eax 中取值.

因此,调用 f来自 C 的代码将不起作用,即使我们将语言链接设置为 C,这也是出现警告的原因。

关于c++ - 如何定义C结构: c-linkage and udt,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51347773/

相关文章:

c++ - 合并两个列表 C++

c++ - if/else 语句的输出不显示/变量赋值问题;初级程序员

c++ - 在同一项目中使用两个不同的数学库会使Visual C++困惑

visual-c++ - 比较 TCHAR 和 VC++ 中的字符串值?

c++ - 有没有办法测试 C++ API(在 ubuntu linux 上)是否可重入(线程安全)?

c++ - 使用 tiled_range 推力 sort_by_key - 不重新排序

c++ - 如何在静态库 (Visual Studio) 中嵌入图标 (.ico)

c++ - 在 Qt CMake 项目中找不到 QCursor

c++ - 在比较两个字符串(整数)之前将字符串转换为整数有什么好处吗?

c++ - 是否可以更改优化校准背景颜色而不是更改图像?