0

我有这个来自 C++ 入门第 5 版:外部链接:

如果一组重载函数中的一个函数是 C 函数,则其他函数必须都是 C++ 函数:

class SmallInt { /* . . .   */ };
class BigNum { /* . . .   */ };
// the C function can be called from C and C++ programs
// the C++ functions overload that function and are callable from C++

extern "C" double calc(double);
extern SmallInt calc(const SmallInt&);
extern BigNum calc(const BigNum&);

calc可以从 C 程序和 C++ 程序调用C 版本。附加函数是带有类参数的 C++ 函数,只能从 C++ 程序中调用。声明的顺序并不重要。

  • 所以我从这些声明中了解到我可以将它们放在标题中。例如:

    // calc.h
    #ifdef __cplusplus
    
    class SmallInt { /* . . .   */ };
    class BigNum { /* . . .   */ };      
    
    // C++ functions can be overloaded
    extern SmallInt calc(const SmallInt&);
    extern BigNum calc(const BigNum&);
    extern "C" 
    
    #endif
    
    double calc(double); // C function
    
  • 那么我需要在 C 源文件中定义 C 版本,在 C++ 源文件中定义 C++ 版本吗?

    // calc.c
    #include "calc.h"
    
    double calc(double){} // do_something
    
    // calc.cxx
    #include "calc.h"
    
    SmallInt calc(const SmallInt&){} // do_something
    BigNum calc(const BigNum&){} // do_something
    
  • 现在我需要这样编译:

     gcc print.c -c && g++ main.cxx print.cxx print.o -o prog
    
  • 它工作得很好,但我的猜测和实现这段代码是否正确?

  • 只要externC++ 版本 (calc(const SmallInt&)和) 不能用 C 编译器编译,它们有什么意义?calc(const BigNum&)太感谢了!

4

2 回答 2

1

不,您可以在 CPP 源文件中定义所有函数,并从 C 中调用它们(如果它们被声明为具有 C 链接,则很容易)。

一个源文件print.cxx可以包含所有三个函数的实现(函数体)。它被编译为C++,其实现double calc(double)当然可以使用C++来完成它的工作。

AC 程序可以与该.o文件链接,并调用calc(double).

为 C++ 库制作 C 可调用 API 会很有用,您可以看到,它必须是 C++ 源代码的一部分才能工作。

当您编写 时extern "C",您是说您将支持从 C 源文件调用该函数。这并不意味着该函数本身是用C编写的。

于 2021-09-09T00:21:54.933 回答
0

当我们谈论“C 链接”时,实际上我们只关心头文件。在头文件中制作函数签名“extern C”就足以让外语(如 rust/go)调用它。

而所谓的“C 链接”有一个对应物,叫做“C++ 链接”。后者在签名中有参数类型,但前者只是简单的函数名称。

例如:编译这个文件:

// example.cpp
#include <array>
using namespace std;
extern "C"
double funcAlpha(double, int){
    return 0;
}

double funcBeta(double, int){
    return 0;
}

int main(){
}

运行gcc example.cpp -o a.out && objdump -t a.out | grep func,你会得到

000000000040046e g     F .text  000000000000001c              _Z8funcBetadi
0000000000400452 g     F .text  000000000000001c              funcAlpha

其中 d = 双倍,i = int

于 2021-09-09T07:48:42.787 回答