C++和C语言函数相互调用之二

linux下c程序c++程序混合编译,c程序中调用c++程序,c语言项目与c++语言项目的合并 把两个开源项目合并到一起,但是一个是c编写,一个是c++编写,在linux环境下实现两个项目的混合编译,以及互相的调用。 阅读详情

1.引言
   C++语言的创建初衷是“abetter C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同。作为一种欲与C兼容的语言,C++保留了一部分过程 式语言的特点(被世人称为“不彻底地面向对象”),因而它可以定义不属于任何类的全局变量和函数。但是,C++毕竟是一种面向对象的程序设计语言,为了支 持函数的重载,C++对全局函数的处理方式与C有明显的不同。

2.从标准头文件说起
       某企业曾经给出如下的一道面试题:

面试题为什么标准头文件都有类似以下的结构?

#ifndef__INCvxWorksh 
#define__INCvxWorksh                                                                             
#ifdef__cplusplus                                                                                
extern"C"{                                                                                     
#endif                                                                                          
#ifdef__cplusplus                                                                               
}                                                                                                
 #endif                                                                                         
  #endif

 

分析  

显然,头文件中的编译宏“#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif” 的作用是防止该头文件被重复引用。

  那么

      #ifdef __cplusplus
      extern "C" {
      #endif 
      #ifdef __cplusplus
      }
      #endif          <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">                                                  </span>

的作用又是什么呢?

3.深层揭密extern "C"
  extern"C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。让我们来详细解读这两重含义。
   被extern "C"限定的函数或变量是extern类型的;
  extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。记住,下列语句:  extern int a;
  仅仅是一个变量的声明,其并不是在定义变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。
   通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函 数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A 编译生成的目标代码中找到此函数。
   与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。
  被extern"C"修饰的变量和函数是按照C语言方式编译和连接的;
  未加extern “C”声明时的编译方式
  首先看看C++中对类似C的函数是怎样编译的。
  作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:       void foo( int x, int y );
  该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。
  _foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。

同样 地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译 器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。
   未加extern "C"声明时的连接方式
  假设在C++中,模块A的头文件如下:

       // 模块A头文件 moduleA.h
         #ifndef MODULE_A_H
         #define MODULE_A_H
         int foo( int x, int y );         #endif
  在模块B中引用该函数:
       // 模块B实现文件 moduleB.cpp 
        #include "moduleA.h"                                     
<span style="white-space:pre">	</span> foo(2,3);                         

        实际上,在连接阶段,连接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号!
   加extern "C"声明后的编译和连接方式
  加extern"C"声明后,模块A的头文件变为:

       // 模块A头文件 moduleA.h
       #ifndef MODULE_A_H
       #define MODULE_A_H
       extern "C" int foo( int x, inty );                                                                                                              
       #endif

  在模块B的实现文件中仍然调用foo( 2,3 ),其结果是:
  (1)模块A编译生成foo的目标代码时,没有对其名字进行特殊处理,采用了C语言的方式;
  (2)连接器在为模块B的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。
  如果在模块A中函数声明了foo为extern "C"类型,而模块B中包含的是extern int foo( int x, int y ) ,则模块B找不到模块A中的函数;反之亦然。
  所以,可以用一句话概括extern“C”这个声明的真实目的(任何语言中的任何语法特性的诞生都不是随意而为的,来源于真实世界的需求驱动。我们在思考问题时,不能只停留在这个语言是怎么做的,还要问一问它为什么要这么做,动机是什么,这样我们可以更深入地理解许多问题):
   实现C++与C及其它语言的混合编程。
  明白了C++中extern "C"的设立动机,我们下面来具体分析extern "C"通常的使用技巧。



4.extern "C"的惯用法
  (1)在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理:

        extern "C"
       {
        #include "cExample.h"                                
       }

  而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern"C"时会出现编译语法错误。
  笔者编写的C++引用C函数例子工程中包含的三个文件的源代码如下:

        

      #ifndef C_EXAMPLE_H
      #define C_EXAMPLE_H
       extern int add(int x,int y);
      #endif      
     #include "cExample.h"
     int add( int x, int y )
     {
            return x + y;
     }
     // c++实现文件,调用add:cppFile.cpp
     extern "C" 
     {
     #include "cExample.h"
     }
     int main(int argc, char* argv[])
     {
            add(2,3); 
            return 0;
      }

      如果C++调用一个C语言编写的.DLL时,当包括.DLL的头文件或声明接口函数时,应加extern "C"{ }

   (2)在C中引用C++语言中的函数和变量时,C++的头文件需添加extern "C",但是在C语言中不能直接引用声明了extern "C"的该头文件,应该仅在C文件中将C++中定义的extern "C"函数声明为extern类型。
  笔者编写的C引用C++函数例子工程中包含的三个文件的源代码如下:

    //C++头文件 cppExample.h
        #ifndef CPP_EXAMPLE_H
        #define CPP_EXAMPLE_H
        extern "C" int add( intx, int y );
        #endif
        //C++实现文件 cppExample.cpp
        #include "cppExample.h"
        int add( int x, int y )
        {
                return x + y;
        }
        
       extern int add( int x, int y );
       int main( int argc, char* argv[] )
      {
             add( 2, 3 ); 
             return 0;
       }

  如果深入理解了第3节中所阐述的extern"C"在编译和连接阶段发挥的作用,就能真正理解本节所阐述的从C++引用C函数和C引用C++函数的惯用法。对第4节给出的示例代码,需要特别留意各个细节。

 

【C++】同项目下,C、C++的相互调用 同一个项目下,C、C++的相互调用 同一个体系下的语言相互调用是要语言兼容的,下面的函数是无法在一个项目中运行成功的。 //.c文件中 int Compare(int a,int b) { return a>b; } //.cpp文件中 extern int Compare(int ,int ); 1、C++调用C接口 //.c文件中 int Compare(int a,int b) {... 阅读详情

相关推荐

【46】C++实战篇——C++函数重载是什么?函数重载需要注意什么?为什么C++支持函数重载,C语言不支持函数重载?C++和C语言代码之间如何相互调用?

摘要: 函数重载是C++的核心特性,允许同名函数通过不同参数列表(类型、数量、顺序)实现多态调用,提升代码可读性和类型安全。C++通过名称修饰(参数类型编码)支持重载,而C语言因简单命名规则无法实现。使用时需注意参数差异、避免歧义,且重载函数需在同一作用域。C/C++互调需用extern "C"声明以禁用名称修饰。相较C语言,C++的重载机制提供了更严格的类型检查和灵活性。

程序员,他们想的是什么?他们想的永远都是技术,他们崇尚的也永远都是技术。 588

c语言函数的调用

学习笔记

qq_53661628的博客 2万+

在C语言源程序中调用API函数ShellExecute

在C语言源程序中调用API函数ShellExecute 详细解答

c语言调用函数

34.C语言规定,一个函数中调用另一个函数(即被调用函数)需要具备的条件有; ①首先被调用的函数必须是已经存在的函数(是库函数或用户自己定义的函数)。②如果使用库函数,一般还应该在本文件开头用#include命令将函数调用有关库函数时所需要到的信息“包含”到本文件中来。 ③如果使用自定义函数,而且该函数与调用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数作声明,即向编译系统声明将要调用此函数,并将有关信息通知编译系统。

qq_74007041的博客 1624

反激变压器设计学习笔记

反激变压器匝比感量设计

m0_55419117的博客 5262

STM32CubeMx + FatFs 实战:SD卡DMA传输中断回调问题深度解析

本文深度解析了在STM32CubeMx环境下,结合FatFs文件系统并使用DMA进行SD卡读写时,程序可能出现的“卡死”问题。核心原因在于HAL库的弱函数回调机制未被正确处理,导致DMA传输完成中断后,状态机锁死。文章提供了两种实战修复方案:直接修改HAL库文件或在用户代码中重写回调函数,并给出了关键的配置检查点与调试技巧,帮助开发者彻底解决SD卡DMA传输中断回调失效的难题。

weixin_29176179的博客 330

C语言与C++语言相互调用

C语言与C++语言相互调用 1 C++调用C中的函数 1.1 C++调用C中的函数(正确使用) 1、案例源文件组成 ...

Andy的博客 2万+

直流并联电压源的下垂控制与模拟光伏板特性的方法与仿真

并联直流电源下垂控制方法,下垂特性可以让并联直流电源输出功率/电流自动均衡,直流电源输出特性模拟光伏板的输出特性,具有自动限制输出最大功率的功能

1197

c语言和c++的相互调用

在实际项目开发中,c和c++代码的相互调用是常见的,c++能够兼容c语言的编译方式,但是c++编译器g++默认会以c++的方式编译程序,而c程序编译器gcc会默认以c的方式编译它,所以c和c++的相互调用存在一定的技巧。1.c方式编译和c++方式编译一般.cpp文件是采用g++去编译,.c文件是采用gcc编译,然而这不是绝对的。 (1)gcc和g++都可以编译.c文件,也都可以编译.cpp文件。g

echo_bright_的博客 2万+

h5页面调用微信JS-SDK分享到微信好友或者朋友圈的配置

1.引入js &lt;script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"&gt;&lt;/script&gt; 2.在页面添加配置 &lt;script type="text/javascript"&gt; var url = location.href..

tiantiandashi的博客 2万+

基于LightGBM和多模型融合的量化交易研究:沪深300为例【附代码】

📊 数据科学与大数据专业 | 数据分析与模型构建 | 数据驱动决策✨ 专业领域:数据挖掘与清洗大数据处理与存储技术机器学习与深度学习模型数据可视化与报告生成分布式计算与云计算数据安全与隐私保护💡 擅长工具:Python/R/Matlab 数据分析与建模Hadoop/Spark 大数据处理平台SQL数据库管理与优化Tableau/Power BI 数据可视化工具TensorFlow/PyTorch 深度学习框架✅数据科学与大数据技术毕业论文【数据】

lagougongzuoshi的博客 1669

Linux下使用C语言封装一个echo命令的函数

Linux下使用 C语言自己封装一个 echo 命令的函数 要求:将该函数封装到环境变量中,并起一个别的名字 #include <stdio.h> #include <string.h> int main(int argv,char* argc[]) { int i; int j; int len; //接收main函数后每个参数的长度 char *p;//用来指向char数组中某个下标的地址 char a[len];//定义一个len

weixin_42535013的博客 1716

基于matlab的CNN验证码识别系统(UI界面版)

基于matlab的CNN验证码识别系统(UI界面版),CNN验证码识别系统包括数据集处理、模型搭建、模型训练、界面设计与实现

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 480

c++与c语言的相互调用方法,C函数和C++函数相互调用

实例解说这个例子,示例了两点C 如何调用C++对象里的函数C++ 如何调用C的函数共两个文件,test.c 和 main.cpp,代码解释如下:在main.cpp (C++ 代码) 里定义了一个类MyMath,类里有个成员函数sum ;如何让C能调用这个c++的函数MyMath::sum呢?即在main.cpp 中添加extern C后,声明定义一个C的函数call_MyMath_sum。在tes...

weixin_28802993的博客 649

游戏服务器框架之跨服(一)

如今的游戏开发,不搞个跨服玩法都不好意思说在做游戏了(当然,也跟游戏类型有关,一些轻度休闲游戏可以排除在外)。跨服玩法的设计,可以进一步激发玩家追求高战力的虚荣心,也可以汇聚玩家数量,避免单服日活跃低呈现死服现象。 几种常见的跨服玩法拓扑结构 一,不同游戏服的玩家进入中立服务器进行战斗,例如跨服天梯类玩法。 游戏服有很多个节点,中心服务器也有很多节点。只要保证对战的双方同时进入同一个中心服游戏进程即可。 二,若干个游戏服组成一个社区,全部服务器包含多个社区,例如世界服玩法。 三,游戏服A玩

littleschemer的博客 5771

[Python] 如何使用 Python 调用 Dify 工作流服务实现自动化翻译

本文介绍了如何使用Python调用Dify的API实现文本翻译自动化。Dify作为AI开发平台,其工作流功能可执行文本处理、翻译等任务。选择Python调用Dify的优势在于职责划分清晰:Dify专注AI服务,Python处理文件操作等非AI任务。

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 1094

C++和C语言函数相互调用

C++代码调用C函数: 在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理: extern "C" { #include "cExample.h" }   而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。   ...

qq_37659294的博客 1035

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

C语言和C++函数相互调用

C语言调用c++函数

m0_64182150的博客 1113

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

C++和C语言函数相互调用

1 引言 C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同。作为一种欲与C兼容的语言,C++保留了一部分过程式语言的特点(被世人称为“不彻底地面向对象”),因而它可以定义不属于任何类的全局变量和函数。但是,C++毕竟是一种面向对象的程序设计语言,为了支持函数的重载,C++对全局函数的处理方式与C有明显的不同。

DaveBobo的博客 1335

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

c++和c语言中的函数相互调用的问题

1、如何C++程序要调用 已编译后的C函数,该怎么办?

多看多听多总结 2808

C和C++语言函数相互调用(转载学习用)

1.引言   C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同。作为一种欲与C兼容的语言,C++保留了一部分过程式语言的特点(被世人称为“不彻底地面向对象”),因而它可以定义不属于任何类的全局变量和函数。但是,C++毕竟是一种面向对象的程序设计语言,为了支持函数的重载,C++对全局函数的处理方式与C有明显的不

zllbuaa的专栏 886

c语言 指针混合编程,C/C++ 混合编程 / 相互接口和函数调用

https://blog.youkuaiyun.com/gatieme/article/details/527306801 C++中调用C的接口我们在阅读一些库的代码的时候, 经常看到有些函数被extern “C”来修饰1.1 extern “C”引入C的库代码如下所示extern "C" void func();1如果需要修饰的函数比较多, 则使用如下方式#ifdef __cplusplus extern ...

weixin_39725885的博客 311

c语言调用c++函数,c与c++的相互调用

最近项目需要使用google test(以下简称为gtest)作为单元测试框架,但是项目本身过于庞大,main函数无从找起,需要将gtest框架编译成静态库使用。因为项目本身是通过纯c语言编写,而gtest则是一个c++编写的测试框架,其中必然涉及c与c++之间的相互调用。注意,本文的前提是,c代码采用gcc等c语言编译器编译c代码,采用g++等c++编译器编译c++代码,如果c和c++代码统一使...

weixin_35867508的博客 4869

C语言调用C++类成员函数讲解和实例

点击蓝字关注我们1、问题成因C语言与C++调用问题原因主要在于C编译器和C++编译器的不同。C是过程式语言,C编译器编译后,函数在符号库中就是函数名,没有其他任何附加信息。而C++是对象式语言,支持函数重载,C++编译器编译后,在符号库中的名字包含了函数名、函数参数类型和函数返回类型等。因此,当两者混合编译时,会相互找不到对象。2、反汇编证明我们通过反汇编来证明上述问题,...

轻松学C语言 5684

C与C++如何互相调用

C/C++不同的语言有不同的编译规则,要想实现通用,就必须告诉编译器,按照目标语言的规则进行编译!

Donge's Blog 4650
上一篇: C C++相互调用
下一篇: C中如何调用C++函数、类内函数
Frideric_Sun
博客等级 码龄16年 20粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值