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

2024-03-19

我有用 C-ABI 接口用 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): 警告 C4190: 'f' 指定了 C 链接,但返回 UDT 'Foo' 与 C 不兼容

(7): 注意:参见 'Foo' 的声明

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

I read C++ 代码链接错误:警告 C4190:类型已指定 C 链接,但返回与 C 不兼容的 UDT https://stackoverflow.com/questions/22901697/error-in-c-code-linkage-warning-c4190-type-has-c-linkage-specified-but-retu,但就我而言,我没有“c++ 代码” 完全在我的 POD 结构中。

我怎样才能让编译器相信这不是C++ struct Foo, but C struct Foo?

我尝试将其移至单独的头文件(.h),但这没有改变任何内容。

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


The x64 调用约定文档 https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2019解释 UDT 返回于eax如果它们足够小并且符合某些标准:

要在 RAX 中按值返回用户定义类型,其长度必须为 1、2、4、8、16、32 或 64 位。它还必须没有用户定义的构造函数、析构函数或复制赋值运算符;没有私有或受保护的非静态数据成员;没有引用类型的非静态数据成员;没有基类;没有虚函数;并且没有不满足这些要求的数据成员。

While Foo is a 标准布局类型(因此我们希望它能够工作),const非静态数据成员使复制赋值运算符被删除,这可能就是他们的意思,即使它说“用户定义”。顺便说一下,这使得它成为一个非平凡类型因此不是 C++03 意义上的 POD。

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

同样,x86 调用约定文档 https://learn.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions?view=vs-2019解释类似的事情:

[...] 8 字节结构除外,这些结构在 EDX:EAX 寄存器对中返回。较大的结构在 EAX 寄存器中作为指向隐藏返回结构的指针返回。 [...]不是 POD 的结构不会在寄存器中返回。

例如,如下所示的函数:

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 的代码也不起作用,这就是出现警告的原因。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何定义C结构:c-linkage和udt 的相关文章

  • 将 System.Drawing.Image 转换为 System.Windows.Media.ImageSource 但没有结果

    我想在我的 WPF 应用程序中将 Image 转换为 ImageSource 我使用正常工作的 Code128 库 已在 WinForms 应用程序中检查 下面的函数返回具有适当大小的 ImageSource 但没有任何内容可见 priva
  • 类型转换 sockaddr 结构

    我正在尝试学习网络编程 并在这个过程中学习C 我对结构感到困惑sockaddr这是一个通用地址 并且sockaddr in 我的书里是这么说的 因此 我们可以填写 sockaddr in 的字段 然后强制转换 a 指向 它指向 指向 soc
  • 实体框架 - 循环更新属性

    我正在尝试找到一种方法来循环 EF 对象的属性并更新这些属性的值 更具体地说 我有 50 个字段 其中最多填充 50 个下拉列表 所有 50 个可能都需要填充 也可能不需要填充 为了解决这个问题 我有一个中继器 最多可以创建 50 个 DD
  • 将数组从 C# 编组到 C++ 并返回:PInvokeStackImbalance

    我有一个 C 函数 我想从 C 访问它 问题是我不断收到 PInvokeStackImbalance 异常 但我不知道为什么 当检查异常被关闭时 一切都运行良好并且符合预期 我的 C 函数的签名是 extern C double solve
  • VBA 中的 VSTO:AddIn.Object 有时不返回任何内容 (null)

    Given VSTO 插件 An override object RequestComAddInAutomationService 它返回一个名为的类的实例Facade在我的场景中 Excel 2007 中的 VBA 宏可访问AddIn O
  • 无法更新 .mdf 数据库,因为该数据库是只读的(Windows 应用程序)

    我使用 C 创建了一个数据库 Windows 应用程序 我的应用程序在 Windows XP 上成功运行 但在 Vista 或 Windows 7 系统上无法正确执行 我的应用程序显示类似以下内容的消息 无法更新 mdf 数据库 因为该数据
  • Code First - 实体框架 - 如何公开外键

    我有以下数据对象 public class Customer System Data Entity ModelConfiguration EntityTypeConfiguration
  • 是否可以用 C# 为 Android 编写应用程序?

    我们都知道Android运行Dalvik VM程序 通常开发人员用 Java 编写程序并将其编译为 Dalvik 字节码 我想知道是否有可能创建一个可以接受 C 代码并将其编译为 Dalvik 字节码的编译器 嗯 这是一种选择 或者您可以在
  • NHibernate 中具有不同类型答案的问题

    我正在尝试找到一个问卷问题的简洁解决方案 假设我有一个Questionnaire类有一个集合Answers e g public class Questionnaire public virtual ISet
  • 允许 .NET WebApi 忽略 DOCTYPE 声明

    我正在尝试通过 WebApi 方法将 XML 反序列化为对象 我有以下课程 XmlRoot IsNullable false public class MyObject XmlElement Name public string Name
  • 读取所有进程内存以查找字符串变量c#的地址

    我有 2 个用 C 编写的程序 第一个名为 ScanMe 的程序包含一个包含值 FINDMEEEEEEE 的字符串变量 以及一个值为 1546 22915487 的双精度变量 另一个名为 MemoryScan 的程序读取第一个程序的所有内存
  • 我可以在C中直接比较int和size_t吗?

    我可以比较一个int and a size t像这样的变量 int i 1 size t y 2 if i y Do something 或者我必须输入其中之一 只要满足以下条件 它就是安全的int为零或正数 如果它是负数 并且size t
  • 选择要重写哪个基类的方法

    鉴于以下情况 class Observer public virtual void Observe Parameter p 0 template
  • gcc 中的“假设”子句

    gcc 最新版本 4 8 4 9 是否有类似于以下的 假设 子句 assume 内置icc支持吗 例如 assume n 8 0 从 gcc 4 8 2 开始 gcc 中没有 assume 的等效项 我不知道为什么 这会非常有用 马夫索建议
  • lambda 表达式是多线程的吗?

    lambda 表达式是多线程的吗 假设当你将数学公式编写为 lambda 方法时 当你将其传递给另一个方法时 它会是多线程的吗 不是100 清楚你问的是什么 您是否想问 lambda 是否自然地在不同的线程上运行 如果是这样 则它们只是 S
  • 父窗体中的居中消息框[重复]

    这个问题在这里已经有答案了 有没有一种简单的方法可以在 net 2 0中将MessageBox居中于父窗体中 我在 C 中确实需要这个并发现中心消息框 C http bytes com topic c sharp answers 26712
  • 使用 LINQ to SQL 的 .NET 架构的最佳设计实践(DAL 必要吗?我们真的可以使用 POCO吗?要采用的设计模式吗?)

    我避免在 net arch n 层架构上编写看起来像是另一个线程的内容 但请耐心等待 希望我和其他人一样 在选择用于企业应用程序的架构时 考虑到当今的趋势和新兴技术 仍然没有 100 满意或不清楚应采取的最佳方法 我想我正在寻求大众社区对方
  • jquery ajax“发布”调用

    我是 jQuery 和 Ajax 的新手 并且在 发布 方面遇到问题 我正在使用 jQuery Ajax post 调用将数据保存到数据库 当我尝试保存数据时 它将 null 传递给我的 C 方法 jQuery 看起来像这样 functio
  • 组合框由于某种原因被链接

    我有以下代码来填充 3 个组合框 private void PopulateDDLs SqlConnection connection SqlCommand command SqlDataReader reader DataTable dt
  • 在 WPF 树视图中获取 FullPath?

    如果我以编程方式创建 WPF TreeView 例如 TreeView treeView lt added in the designer TreeViewItem rootNode new TreeViewItem rootNode He

随机推荐