语言链接

提供以不同程序语言编写的模块间的连接。

extern 字符串字面量 { 声明序列(可选) }     (1)
extern 字符串字面量 声明     (2)

1) 将语言说明字符串字面量应用到声明于声明序列中的所有函数类型,具有外部连接的函数名,和具有外部连接的变量。
2) 将语言说明字符串字面量应用到单一声明或定义。
字符串字面量 - 所要求的语言连接的名字
声明序列 - 声明的序列,可以包含嵌套的连接说明
声明 - 一个声明
[编辑] 解释
所有函数类型,所有拥有外部连接的函数名,及所有拥有外部连接的变量名,拥有一种称作语言连接的性质。语言连接封装与以另一程序语言编写的模块进行连接的要求的集合:调用约定、名字重整的算法,等等。仅保证支持二种语言连接:
1) “C++”,默认的语言连接。
2) “C”,使得以 C 程序语言编写的函数进行连接,以及在 C++ 程序中定义能从C模块调用的函数成为可能。

extern "C" {
    int open(const char *pathname, int flags); // C 函数声明
}

int main()
{
    int fd = open("test.txt", 0); // 从 C++ 程序调用 C 函数
}

// 此 C++ 函数能从 C 代码调用
extern "C" void handler(int) {
    std::cout << "Callback invoked\n"; // 它能使用 C++
}

因为语言连接是每个函数类型的一部分,故函数指针也要维持语言连接。函数类型的语言连接(它表示调用约定)和函数名的语言离近了(它表示名字重整)是彼此独立的:

extern "C" void f1(void(*pf)()); // 声明一个具有 C 连接的函数 f1,
                             // 它返回 void 并接受指向返回 void 且不接受形参的 C 函数的指针
extern "C" typedef void FUNC(); // 声明 FUNC 为返回 void 且不接受形参的 C 函数类型
FUNC f2;            // 名字 f2 拥有 C++ 连接,但其类型是 C 函数
extern "C" FUNC f3; // 名字 f3 拥有 C 连接且其类型是 C 函数 void(void)
void (*pf2)(FUNC*); // 名字 pf2 拥有 C++ 连接,且其类型是“指向返回 void 并接受
                    // 一个‘指向返回 void 且不接受形参的 C 函数的指针’类型参数的 C++ 函数的指针
extern "C" {
    static void f4(); // 函数 f4 的名字拥有内部连接(无语言)
                      // 但函数的类型拥有 C 语言连接
}

在同一命名空间中具有相同名字和相同形参列表的两个函数,不能拥有两个不同的语言连接(然而需要注意,形参的连接可容许这种重载,例如 std::qsort 和 std::bsearch 的情况)。类似地,同一命名空间中的两个变量不能拥有两种不同的语言连接。
[编辑] “C” 连接的特殊规则
1) 当类成员的声明和成员函数类型的声明出现于 “C” 语言块中时,其连接仍保持为 “C++”。
2) 当两个拥有同一无限定名字的函数声明于不同命名空间,且都拥有 “C” 语言连接时,两个声明表示同一函数。
3) 当两个拥有 “C” 语言连接和相同名字的变量出现于不同命名空间时,它们表示同一变量。
4) 一个 “C” 变量和一个 “C” 函数不能拥有相同的名字,无关乎它们定义于同一或不同命名空间。
语言连接只能出现在命名空间作用域。语言说明的花括号不建立作用域。当语言说明发生嵌套时,有效的是最内层的说明。函数可在带语言说明的声明之后,进行不带连接说明的重声明,第二个声明将重复使用首个声明的语言连接。反之则不行:若首个声明无语言连接,则假定其为 “C++”,而以其他语言连接重声明则是错误。
直接包含于语言连接说明之中的声明,被处理为如同它含有 extern 说明符,用以确定所声明的名字的连接以及它是否为定义。

extern "C" int x; // 声明且非定义 // 上一行等价于 extern "C" { extern int x; }
extern "C" { int x; } // 声明及定义
extern "C" 使得在 C++ 程序中包含(include)含有 C 库函数的声明的头文件成为可能,但如果与 C 程序共用相同的头文件,必须以适当的 #ifdef 隐藏 extern "C"(其在 C 中不被允许),通常为 __cplusplus:
#ifdef __cplusplus
extern "C" int foo(int, int); // C++ 编译器所见
#else
int foo(int, int);            // C 编译器所见
#endif

   转载规则


《语言链接》 吴杭沉 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
数组 数组
前言在C语言中,数组和指针似乎总是“暧昧不清”,有时候很容易把它们混淆。本文就来理一理数组和指针之间到底有哪些异同。 数组回顾在分析之前,我们不妨回顾一下数组的知识。数组是可以存储一个固定大小的相同类型元素的顺序集合。为了便于我们说明,假设
2024-08-14
下一篇 
枚举申明 枚举申明
枚举(enumeration)是独立的类型,其值限制在一个取值范围内(细节见下文),它可以包含数个明确命名的常量(“枚举项(enumerator)”)。各常量的值是某个整型类型(称为该枚举的底层类型(underlying type))的值。
2024-08-04
  目录