【C与C++的相互调用方法】

这篇具有很好参考价值的文章主要介绍了【C与C++的相互调用方法】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C与C++为什么相互调用的方式不同

  C 和 C++ 之间的相互调用方式存在区别,主要是由于 C 和 C++ 语言本身的设计和特性不同。

  • 函数调用和参数传递方式不同:C 和 C++ 在函数调用和参数传递方面有一些不同之处。C 使用标准的函数调用约定,而 C++ 在函数调用中可能包含额外的信息,如函数重载和默认参数。为了正确匹配函数签名,C++ 编译器可能会在函数名上进行名称修饰(name mangling)。
  • 函数重载和名称修饰:C++ 支持函数重载,即可以有相同的函数名但不同的参数列表。为了在可执行文件中区分这些重载函数,C++ 编译器会在函数名中添加一些信息,以便于重载解析。这与 C 的函数名约定不同,C 中函数名是平铺的。
  • 链接库的差异:C 和 C++ 编译器链接不同的标准库。C 编译器链接 C 标准库,而 C++ 编译器链接 C++ 标准库。由于标准库可能涉及不同的函数和数据结构,因此在链接阶段可能会有不同的处理。
  • 编译器特性:C 和 C++ 编译器对代码的解析、优化、链接等可能会有不同的处理方式,这可能会导致在 C 和 C++ 相互调用时需要进行适当的处理。

  解决手段:为了在 C 和 C++ 之间实现相互调用,C++ 引入了 extern “C” 语法,它可以用来告诉 C++ 编译器在函数声明上使用 C 的调用约定,以便在链接阶段能够正确解析函数名。这种设计是为了在 C 和 C++ 之间实现互操作性,但由于两者的语法和特性存在差异,因此在调用方式、编译器行为和链接方式上会存在一些差异。

C++中调用C

  话不多说,直接上案例,下面是一个简单的示例,演示了如何在 C++ 代码中调用 C 函数:

首先分别创建三个文件:mylib.cmylib.hmain.cpp

  mylib.c如下:

// mylib.c
#include <stdio.h>

void my_c_function() {
    printf("This is a C function.\n");
}

  mylib.h如下:

// mylib.h
#ifndef MYLIB_H
#define MYLIB_H

void my_c_function();

#endif // MYLIB_H

  main.cpp如下:

// main.cpp
#include <iostream>

extern "C" {
    // 声明 C 函数的原型
    void my_c_function();
}

int main() {
    std::cout << "Calling a C function from C++:" << std::endl;

    // 调用 C 函数
    my_c_function();

    return 0;
}

  在这个示例中,我们使用了 #include "mylib.h" 来引入头文件,并在 C++ 中调用了 my_c_function()。这样就能正确地在 C++ 中调用 C 函数。编译步骤如下:

gcc -c mylib.c -o mylib.o   # 编译 C 文件为目标文件
g++ -c main.cpp -o main.o   # 编译 C++ 文件为目标文件
g++ main.o mylib.o -o app  # 链接目标文件生成可执行文件

  编译后的文件列表如下:
【C与C++的相互调用方法】,c++,Linux,c语言,c++
  然后运行可执行文件:./app得到输出结果:
【C与C++的相互调用方法】,c++,Linux,c语言,c++
  这里可以使用objdump命令查看编译之后的中间文件mylib.omain.o的符号表:
【C与C++的相互调用方法】,c++,Linux,c语言,c++
【C与C++的相互调用方法】,c++,Linux,c语言,c++
  可以发现,my_c_function()函数编译出的名称在mylib.omain.o是相同。这是由于 C++ 文件中使用 extern “C” 来声明 C 调用约定,以便 C 能够正确解析函数名。
  我们来看看如果没有使用extern “C” 后的编译情况吧:
【C与C++的相互调用方法】,c++,Linux,c语言,c++
  可以发现,不使用 extern “C”, 函数 my_c_function 编译后名称变为了 (_Z13my_c_functionv)
  是由于在C++中,函数名在编译后会根据函数的参数类型和返回类型进行名称重整(Name Mangling),以支持函数重载等特性。这是因为C++支持函数的参数类型和个数可以不同,所以需要在编译后为每个函数生成一个唯一的名称。
  当你在C++中调用一个C函数时,如果不使用 extern “C” 声明,C++ 编译器会默认对函数名进行名称重整。而在C语言中,函数名不会被重整。
  如果你在C++中调用了一个C函数,并且没有使用 extern “C” 声明,C++ 编译器会对函数名进行名称重整,生成一个新的名字,类似 _Z13my_c_functionv 这样的名称。这个过程被称为名称重整(Name Mangling),是为了确保函数在C++中能够正确处理函数重载等特性。

C中调用C++

  下面还是来看一个简单的示例,演示了如何在 C 代码中调用 C++ 函数:

首先分别创建三个文件:mylib.cppmylib.hmain.c

  mylib.cpp如下:

// mylib.cpp
#include <iostream>

#include "mylib.h"

void my_cpp_function(int num) {
    std::cout << "C++ function called with number: " << num << std::endl;
}

  mylib.h如下:

// mylib.h
#ifndef MYLIB_H
#define MYLIB_H

#ifdef __cplusplus
extern "C" {
#endif

    void my_cpp_function(int num);

#ifdef __cplusplus
}
#endif

#endif // MYLIB_H

#endif // MYLIB_H

  main.c如下:

// c_main.c
#include <stdio.h>

#include "mylib.h"

int main() {
    printf("Calling C++ function from C\n");
    
    // Call the C++ function
    my_cpp_function(42);
    
    return 0;
}

  在这个示例中,我们使用了 #include "mylib.h" 来引入头文件,并在 main.c 中调用了 my_cpp_function()。这样就能正确地在 C 中调用 C++ 函数。编译步骤如下:

g++ -c mylib.cpp -o mylib.o   # 编译 C 文件为目标文件
gcc -o main main.c mylib.o -lstdc++  # 链接目标文件生成可执行文件

注释-lstdc++ 是用于链接 C++ 标准库的编译选项。在Linux系统中,C++ 标准库通常被命名为 libstdc++.so,使用 -lstdc++ 编译选项可以将这个库链接到可执行文件中,以便在运行时使用C++的标准库函数和功能。

  如果缺少 -lstdc++ 则会报错:
【C与C++的相互调用方法】,c++,Linux,c语言,c++
  编译后的文件列表如下:
【C与C++的相互调用方法】,c++,Linux,c语言,c++
  然后运行可执行文件:./main得到输出结果:
【C与C++的相互调用方法】,c++,Linux,c语言,c++
  这里解释一下mylib.h头文件中的 #ifdef __cplusplus:在main.c文件夹中调用mylib.h头文件,但是 C 语言中并没有 extern 这个关键字,因此,使用 #ifdef __cplusplus来充当一个译时候的阀门。
  总结一下:对于C调用C++的情况,没有 extern “C” 这样的关键字。您需要在C++代码中使用 extern “C” 来确保C++函数按照C的方式进行链接,同时在C代码中包含相应的头文件并调用这些函数。

致谢

  本文的学习参考了以下文章:C与C++如何互相调用文章来源地址https://www.toymoban.com/news/detail-655287.html

到了这里,关于【C与C++的相互调用方法】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【前端】在Vue页面中引入其它vue页面 数据传输 相互调用方法等

    1.this.$emit ,子传父 2.this.$children属性 this.$children返回的是数组 例子: 3.通过this.$refs获取组件 4.this.$parent获取父组件数据 this.$parent返回的是对象,this.$children返回的数组 例子: 需求         在 home.vue 中引用 headView.Vue 方案: home.vue 代码: 只需要在home.vue 想要的地方添加 

    2024年02月07日
    浏览(38)
  • linux远程服务器和本地服务器相互之间传输文件方法SSH(乌班图系统)

    提前知道几点 : 1.使用的 MobaXterm软件 2.访问本地、远程服务器,需要账号和密码(远程机器上的 用户名和密码 远程机器的 IP 地址或主机名(在同一子网上))。每次访问需要输入密码,可以搜 Ubuntu SSH 免密登录 3.主要是先要访问本地服务器,才能访问远端服务器,显卡装

    2024年02月15日
    浏览(58)
  • C++异步调用方法

    future和promise的作用是在不同线程之间传递数据。使用指针也可以完成数据的传递,但是指针非常危险,因为互斥量不能阻止指针的访问;而且指针的方式传递的数据是固定的,如果更改数据类型,那么还需要更改有关的接口,比较麻烦;promise支持泛型的操作,更加方便编程

    2024年02月07日
    浏览(29)
  • Go语言中,如何调用C++的dll文件

    我将给出一个完整的示例来说明如何调用C++ DLL文件。首先,我们将创建一个简单的C++ DLL,然后编写Go代码来调用该DLL。 创建C++ DLL文件( example.cpp ): 编译C++代码为DLL文件: 使用MinGW编译器编译 example.cpp 文件,生成 example.dll 文件。 -Wl,–out-implib,libexample.a -Wl,–output-def,exa

    2024年03月12日
    浏览(109)
  • OC与Swift的相互调用

    1、在 Build Settings 搜索 Packaging ,设置 Defines Module 为 YES  2、新建 LottieBridge.swift 文件,自动生成桥 ProductName-Bridging-Header.h  3、在 LottieBridge.swift 中,定义Swift类继承于OC类,声明 @objcMembers 或 @objc ,实现相关方法 4、在OC代码中引用 ProductName-Swift.h ,调用Swift相关方法 1、在 Pr

    2024年02月14日
    浏览(44)
  • python 调用c语言方法详解

      Python是一种强大的编程语言, Python在代码的编写中可以使用任何一种编程语言,可以利用其内置函数或模块来完成自己的任务。但是在 Python中调用其他语言的程序时,需要有特定的环境,例如:C、C++等。 在 python中调用其他语言程序有很多方法,目前常用的有 pycharm、 l

    2024年02月11日
    浏览(42)
  • SpringMVC 怎么和 AJAX 相互调用的

    通过 Jackson 框架就可以把 Java 里面的对象直接转化成 Js 可以识别的 Json 对象。 步骤如下 : a、加入 Jackson.jar b、在配置文件中配置 json 的映射 c、在接受 Ajax 方法里面可以直接返回 Object,List 等,但方法前面要加上@ResponseBody 详细步骤: 在 SpringMVC 中配置一个控制器来处理 AJAX

    2024年02月15日
    浏览(40)
  • 【知识点】python中类的相互调用

    在 Python 中,类可以相互调用。这意味着一个类可以访问另一个类的方法或属性。下面是几个例子: 在同一个文件内,不同类的相互调用例子如下: 代码 在上面的代码中, Dealership 类调用了 Car 类。它通过创建一个 Car 对象来添加汽车,并通过循环遍历汽车列表来显示汽车的

    2023年04月10日
    浏览(36)
  • 使用C++调用Yolo模型的方法与步骤

    目录 ## 1. 引言 ## 2. Yolo算法简介 ## 3. 准备工作 ## 4. 安装依赖库 ## 5. 下载Yolo模型权重文件 ## 6. 加载Yolo模型 ## 7. 图像预处理 ## 8. 目标检测与后处理 ## 9. 结果可视化 ## 10. 总结 随着计算机视觉技术的不断发展,目标检测在许多应用领域都起到了重要作用。Yolo(You Only Look Onc

    2024年02月16日
    浏览(33)
  • c++和QT子类调用父类方法

    c++调用方式 : 父类名::方法名 QT调用方式 : __super::方法

    2024年02月13日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包