ein*_*ica 5 c c++ cross-language include extern-c
我正在编写一个 C 库,它可能对编写 C++ 的人有用。它有一个标题,如下所示:
#ifndef FOO_H_
#define FOO_H_
#include <bar.h>
#include <stdarg.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
void foo_func();
#ifdef __cplusplus
}
#endif
#endif
Run Code Online (Sandbox Code Playgroud)
我想知道 - 我应该在extern "C"包含标头包含指令之前移动该位吗?尤其是在实践中,其中一些标头本身可能有一个extern "C"?
不,一般来说,您不应该移动它以包含标题。
extern "C"用于指示函数正在使用 C 调用约定。声明对变量和 s 没有影响#define,因此不需要包含这些。如果 an#include位于extern "C"块内,则这会有效地修改该头文件内的函数声明!
背景:如果没有extern "C"声明,则在使用 C 编译器编译时,假定函数遵循 C 约定,而在使用 C++ 编译器编译时,假定函数遵循 C++ 约定。如果 C 和 C++ 代码使用相同的头文件,则会出现链接器错误,因为编译后的函数在 C 和 C++ 中具有不同的名称。
虽然可以将所有代码放在 #ifdef 块之间,但我个人不喜欢它,因为它实际上仅用于函数原型,而且我经常看到人们将其复制粘贴到不应该的地方。最简洁的方法是将其保留在应有的位置,即 C/C++ 头文件中的函数原型周围。
因此,为了回答您的问题“我应该extern "C"在包含标头包含指令之前移动该位吗?”,我的答案是:不,您不应该。
但这可能吗?是的,在很多情况下这不会破坏任何东西。有时,如果外部头文件中的函数原型不正确(例如,当它们是 C 函数并且您想从 C++ 调用它们时)并且您无法更改该库,则甚至有必要。
然而,在某些情况下,这样做会破坏构建。这是一个简单的示例,如果使用以下内容包装包含,则无法编译extern "C":
foo.h:
#pragma once
// UNCOMMENTING THIS BREAKS THE BUILD!
//#ifdef __cplusplus
//extern "C" {
//#endif
#include "bar.h"
bar_status_t foo(void);
//#ifdef __cplusplus
//}
//#endif
Run Code Online (Sandbox Code Playgroud)
foo.c:
#include <stdio.h>
#include "foo.h"
#include "bar.h"
bar_status_t foo(void)
{
printf("In foo. Calling bar wrapper.\n");
return bar_wrapper();
}
Run Code Online (Sandbox Code Playgroud)
酒吧.h:
#pragma once
typedef enum {
BAR_OK,
BAR_GENERIC_ERROR,
BAR_OUT_OF_BEAR,
// ...
} bar_status_t;
extern "C" bar_status_t bar_wrapper(void);
bar_status_t bar(void);
Run Code Online (Sandbox Code Playgroud)
酒吧.cpp:
#include <iostream>
#include "bar.h"
extern "C" bar_status_t bar_wrapper(void)
{
std::cout << "In C/C++ wrapper." << std::endl;
return bar();
}
bar_status_t bar(void)
{
std::cout << "In bar. One bear please." << std::endl;
return BAR_OK;
}
Run Code Online (Sandbox Code Playgroud)
主要.cpp:
#include <stdio.h>
#include <stdlib.h>
#include "foo.h"
#include "bar.h"
int main(void)
{
bar_status_t status1 = foo();
bar_status_t status2 = bar();
return (status1 != BAR_OK) || ((status2 != BAR_OK));
}
Run Code Online (Sandbox Code Playgroud)
取消注释ah中的块时,出现以下错误:
main2.cpp:(.text+0x18): undefined reference to `bar'
collect2.exe: error: ld returned 1 exit status
Makefile:7: recipe for target 'app2' failed
Run Code Online (Sandbox Code Playgroud)
没有的话,它构建得很好。无论哪种方式,仅从 foo 和 bar 调用 C 函数的 AC main 都可以很好地构建,因为它不受块的影响#ifdef __cplusplus。
| 归档时间: |
|
| 查看次数: |
1596 次 |
| 最近记录: |