繁体   English   中英

将C ++结构传递给期望C结构的库

[英]Passing C++ struct to library expecting C struct

我正在Linux中编写一个C ++程序,需要使用用C编写的旧库。库使用C结构将信息传入和传出函数,这些结构是字节对齐的(无填充)。

我的理解是C ++中的结构实际上是一个对象,而C中的结构只是一个内存块,被分成可单独寻址的部分。

如何在C ++中创建C样式结构以传递给库? (我不能传递一个对象)

你在这里问两个问题,真的......

如何在C ++中创建C样式结构?

代替

struct foo { /* ... */ };

使用

extern "C" {
    struct foo { /* ... */ };
}

这可能不会导致任何不同,即“C ++样式结构”和“C样式结构”通常是相同的,只要您不添加方法,受保护的成员和位字段。 但是,由于函数需要“extern C”,所以在这些大括号中包含所有用于C的代码是合理的。

有关更多详细信息,请参阅: 外部“C”在C ++中的作用是什么? 和@AndrewHenle的评论。


我...需要使用用C编写的库

我在这里解释一个正式的C ++ FAQ项目 ,告诉你(惊讶,惊讶)只是在一个extern C块中包含库头,然后像你编写C一样使用它中的任何内容:

extern "C" {
  // Get declaration for `struct foo` and for `void f(struct foo)`
  #include "my_c_lib.h"
}

int main() {
    struct foo { /* initialization */ } my_foo;
    f(my_foo);
}

我的理解是C ++中的结构实际上是一个对象,而C中的结构只是一个内存块,被分成可单独寻址的部分。

你刚才用不同的词语描述了几乎完全相同的东西。

由于两种语言的语法重叠,您通常可以使用struct关键字定义的简单类,并使用C编译器编译相同的定义。

此外,您通常可以将指向用户定义类型的对象的指针从C ++程序传递到C程序。 但是,您通常希望将该定义包装在extern "C"中,以便告诉计算机您希望这种兼容性。

最后,请记住,在C ++中,关键字class和关键字struct都引入了一个类定义,因此C ++实际上没有“结构”,但在C中它们绝对是一个东西(而类不是)。 因此,只需要小心使用术语。

所以,这个问题有一些与之相关的复杂问题。 但是,对于第一个近似,答案很简单。

C编译器和C ++编译器(大多数C编译器都接受它们)将接受的任何C struct声明都将是“ 标准布局类型 ”。 这是C ++标准中定义的概念,C ++编译器应该以某种方式对待它们。

特别是,符合C ++编译器符合的ABI(也称为应用程序二进制接口)子集的C编译器应具有与此类型完全相同的内存表示。

对于Linux和Windows,ABI都经过了C和C ++的精心定义,现在已经有5到10年了。 任何平台上的所有编译器都应该符合它。 所以对于任何常见的C和C ++编译器组合都是如此。 这包括Clang,g ++,Visual Studio,基本上几乎任何在该平台上都不具备高度专业性的编译器。 这并不一定意味着标准C ++库的不同版本具有兼容的实现,因为(例如)多年来实现::std::string的方式(因此字符串结构中实际存在哪些数据)尽管公共界面没有太大变化,但已经发生了巨大的变化。

C ++ ABI由于一些不同的因素而变得复杂。 其中包括异常处理和函数名称修改(在函数的链接器符号名称中编码函数参数的类型)约定。 此外,由于在很多情况下和其他问题中类型默认为int的方式,C很大程度上要求调用者在函数完成后从堆栈中弹出参数,因为被调用的函数无法确定参数的大小已经被推上了。 C ++有更严格的类型检查,有一段时间这导致了一个'被调用函数弹出参数'调用约定。 我认为不再是这种情况了,因为我认为它的效率较低。 我可能错了。

现在,如果您开始使用编译器特定的关键字,如'packed'或'aligned',这一切都会消失。 然后,您应该仔细查阅文档以了解会发生什么。

人们提到了一个extern "C"声明。 这些对于C和C ++代码之间的接口很重要,但它们与struct布局无关,根本不需要它。 什么extern "C"声明是好的,声明函数名称和调用约定符合C ABI而不是C ++ ABI。 这是关于调用者是否从堆栈或被调用函数中弹出函数调用参数,函数名称如何变为符号以供链接器使用,订单参数被推入堆栈,等等。 同样,关于结构如何在内存中布局的内容与extern "C"无关。 该构造完全是关于函数,而不是struct

并且,为了重新迭代,这里有很多复杂性。 但在绝大多数情况下,您根本不需要担心它。 它会起作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM