结合C ++和C - 如何#IFDEF __cplusplus工作? [英] Combining C++ and C - how does #ifdef __cplusplus work?

查看:348
本文介绍了结合C ++和C - 如何#IFDEF __cplusplus工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的工作,有很多传统的 C code的一个项目。我们已经开始用C ++编写,意图最终转换遗留code,以及。我有点困惑如何在 C 和C ++进行交互。据我所知,通过与的externC包装在 C code中的C ++编译器不会裂伤在 C code的名字,但我不完全知道如何实现这一点。

所以,在每一个顶部的 C 头文件(后包括后卫),我们有

 的#ifdef __cplusplus
为externC{
#万一

和底部,我们写

 的#ifdef __cplusplus
}
#万一

在这两者之间,我们有我们所有的包括类型定义和函数原型。我有几个问题,看看我这个正确理解:


  1. 如果我有一个C ++文件A.hh这
    包括 C 头文件B.h,
    包括其他的 C 头文件C.h,
    这个怎么用?我觉得
    当编译器步入B.h,
    __ CPLUSPLUS 将被定义,所以它
    将包装code。与的externC
    (和 __ CPLUSPLUS 将不
    此块中定义)。所以,
    当它步入C.h,
    __ CPLUSPLUS 将不会被定义
    和code将不会被包裹在
    的externC。这是正确的?


  2. 这有什么错
    包装采用了一块code的
    的externC{的externC{..}}
    什么将在第二的externC
    怎么办?


  3. 我们不会把这个包装周围的.c文件,只是.h文件。所以,如果一个函数没有原型,会发生什么?该编译器认为这是一个C ++函数?


  4. 我们也使用一些第三方
    这是写在 C ,并执行code
    没有这种包装的周围
    它。任何时候,包括我一个头
    从库中,我已经把
    一个的externC周围的#include。
    这是对付正道
    是什么?


  5. 最后,开设了一个好主意吗?
    还有什么,我们应该怎么办?
    我们将要混合的 C 和C ++
    在可预见的未来,我
    要确保我们涵盖了所有
    我们的基地。



解决方案

的externC并没有真正改变编译器读取code的方式。如果你的code是一个.c文件,它会被编译为C,如果是在一个.cpp文件,它会被编译为C ++(除非你做你的配置一些奇怪的事情)。

什么的externC确实是影响联动。 C ++函数,编译时,其名称有错位 - 这是什么使得超载成为可能。函数名称获取基于类型和参数个数修改,使具有相同名称的两个函数都会有不同的符号名称。

code内的的externC仍是C ++ code。还有你可以在externC块做什么限制,但他们都对联动。您不能定义不能用C链接建立任何新的符号。这意味着没有类或模板,例如。

的externC块窝很好。还有的externC ++如果你发现自己无可救药地陷的的externC区域内,但它不是' T使得一个好主意,从清洁的角度。

现在,特别是关于您的问题编号:

关于#1:__cplusplus应的的externC块内定义。这不要紧,不过,因为块应该窝整齐。

关于#2:__cplusplus会为正在通过C ++编译器运行任何编译单元定义。通常情况下,这意味着.cpp文件和被纳入由.cpp文件的任何文件。同样.H(或.hh或.HPP或者什么具备的,你)可能是因为PTED C或C ++在不同的时间间$ P $,如果不同的编译单元囊括其中。如果你想在.h文件中的原型,参考C符号名,那么他们必须有的externC是间preTED为C ++时,他们应该不会有的externC是PTED为C间$ p $的时候 - 因此的#ifdef __cplusplus 检查

要回答你的问题#3:没有原型的功能将C ++链接,如果他们在.cpp文件,而不是内部的的externC块。这是好的,但是,因为如果它有没有原型,它只能通过其他功能在同一个文件调用,然后你不普遍关心的联动是什么样子,因为你不打算具有该功能由同一编译单元反正以外的任何调用。

有关#4,你就完全理解这。如果你是其中的code的头部有C链接(如code,它是由一个C编译器编译),则必须的externC标题 - 这样你就能与库链接。 (否则,你的链接将寻找职能,如 _Z1hic 的名字,当你在寻找无效小时(INT,CHAR)

5:这种类型的混合是一种常见的理由使用的externC,我没有看到什么不好做这种方式 - 只是使确保你知道你在做什么。

I'm working on a project that has a lot of legacy C code. We've started writing in C++, with the intent to eventually convert the legacy code, as well. I'm a little confused about how the C and C++ interact. I understand that by wrapping the C code with extern "C" the C++ compiler will not mangle the C code's names, but I'm not entirely sure how to implement this.

So, at the top of each C header file (after the include guards), we have

#ifdef __cplusplus
extern "C" {
#endif

and at the bottom, we write

#ifdef __cplusplus
}
#endif

In between the two, we have all of our includes, typedefs, and function prototypes. I have a few questions, to see if I'm understanding this correctly:

  1. If I have a C++ file A.hh which includes a C header file B.h, includes another C header file C.h, how does this work? I think that when the compiler steps into B.h, __cplusplus will be defined, so it will wrap the code with extern "C" (and __cplusplus will not be defined inside this block). So, when it steps into C.h, __cplusplus will not be defined and the code will not be wrapped in extern "C". Is this correct?

  2. Is there anything wrong with wrapping a piece of code with extern "C" { extern "C" { .. } }? What will the second extern "C" do?

  3. We don't put this wrapper around the .c files, just the .h files. So, what happens if a function doesn't have a prototype? Does the compiler think that it's a C++ function?

  4. We are also using some third-party code which is written in C, and does not have this sort of wrapper around it. Any time I include a header from that library, I've been putting an extern "C" around the #include. Is this the right way to deal with that?

  5. Finally, is this set up a good idea? Is there anything else we should do? We're going to be mixing C and C++ for the foreseeable future, and I want to make sure we're covering all our bases.

解决方案

extern "C" doesn't really change the way that the compiler reads the code. If your code is in a .c file, it will be compiled as C, if it is in a .cpp file, it will be compiled as C++ (unless you do something strange to your configuration).

What extern "C" does is affect linkage. C++ functions, when compiled, have their names mangled -- this is what makes overloading possible. The function name gets modified based on the types and number of parameters, so that two functions with the same name will have different symbol names.

Code inside an extern "C" is still C++ code. There are limitations on what you can do in an extern "C" block, but they're all about linkage. You can't define any new symbols that can't be built with C linkage. That means no classes or templates, for example.

extern "C" blocks nest nicely. There's also extern "C++" if you find yourself hopelessly trapped inside of extern "C" regions, but it isn't such a good idea from a cleanliness perspective.

Now, specifically regarding your numbered questions:

Regarding #1: __cplusplus should be defined inside of extern "C" blocks. This doesn't matter, though, since the blocks should nest neatly.

Regarding #2: __cplusplus will be defined for any compilation unit that is being run through the C++ compiler. Generally, that means .cpp files and any files being included by that .cpp file. The same .h (or .hh or .hpp or what-have-you) could be interpreted as C or C++ at different times, if different compilation units include them. If you want the prototypes in the .h file to refer to C symbol names, then they must have extern "C" when being interpreted as C++, and they should not have extern "C" when being interpreted as C -- hence the #ifdef __cplusplus checking.

To answer your question #3: functions without prototypes will have C++ linkage if they are in .cpp files and not inside of an extern "C" block. This is fine, though, because if it has no prototype, it can only be called by other functions in the same file, and then you don't generally care what the linkage looks like, because you aren't planning on having that function be called by anything outside the same compilation unit anyway.

For #4, you've got it exactly. If you are including a header for code that has C linkage (such as code that was compiled by a C compiler), then you must extern "C" the header -- that way you will be able to link with the library. (Otherwise, your linker would be looking for functions with names like _Z1hic when you were looking for void h(int, char)

5: This sort of mixing is a common reason to use extern "C", and I don't see anything wrong with doing it this way -- just make sure you understand what you are doing.

这篇关于结合C ++和C - 如何#IFDEF __cplusplus工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆