精华内容
下载资源
问答
  • C和C++混合编程问题

    2020-09-03 07:08:08
    主要介绍了C和C++混合编程问题,需要的朋友可以参考下
  • c和c++混合编程代码

    2015-09-05 23:00:38
    c和c++混合编程的例子代码可以直接运行里面的例子很丰富每一段都有注释解释适合了解c和c++混合编程的人员了解
  • 更多请参考我的链接:http://blog.csdn.net/haohaojian/article/details/54630572
  • MATLAB与C/Visual C++混合编程的实现.pdf 更多资源请点击:https://blog.csdn.net/weixin_44155966
  • C/C++和C#混合编程

    2017-11-01 21:31:11
    这是对C/C++代码 封装 可以用C#调用。事实上,C系列中还存在一种语言叫做托管C++,这种语言语法上和C++几乎一样,但是却C#一样编译成为微软中间语言,这样就可以C#良好地通信,即可以在c#中使用托管C++
  • CC++混合编程

    2021-01-13 23:07:43
    一、CC++混合编程的原理 首先,我先了解一下编译的过程。分为四步:预处理(预处理用于将所有的#include头文件以及宏定义替换成其真正的内容)——编译(将经过预处理之后的程序转换成特定汇编代码(assembly code)的...

    一、C与C++混合编程的原理

    首先,我先了解一下编译的过程。分为四步:预处理(预处理用于将所有的#include头文件以及宏定义替换成其真正的内容)——编译(将经过预处理之后的程序转换成特定汇编代码(assembly code)的过程)——汇编(汇编过程将上一步的汇编代码转换成机器码)——链接(链接过程将多个目标文以及所需的库文件(.so等)链接成最终的可执行文件).

    可以看下原文,大致了解一下:https://www.cnblogs.com/carpenterlee/p/5994681.html

    在这里,就不过多分析编译原理,把重心放在如何实现C与C++混合编程的问题上。

    我们知道,C语言的发展快五十年了,它积累很多优秀的项目和库,丢弃了很可惜,重写也没必要,那就研究如何在C++中调用它。

    C++调用C语言的原理是什么?

    其实,C++的编译和C语言是一样的,都要经过四步。前四步是对文件单独处理,而最后一步(链接)则是全员处理。

    混合编程的”混合“操作发生在链接这一步。

    c++链接时候,能够找到对应的c语言函数的符号,那就意味着实现了混合编程。

    二、存在的难点

    先摆出结论:

    C++编译后,函数的符号会加上前后缀(与形参的类型有关),这样做的好处是可以实现函数的多态(即根据你输入的形参类型来调用相应的函数)。

    而C语言编译后,妥妥地一个没有加工的函数名。

    所以,要解决的问题是,如何让C++成功链接上(或者对应上,又或者找得上)C语言的符号。

     

    测试一:c++ 同名的函数编译,然后反汇编查看符号表。

    #include <iostream>
    
    int add(int a, int b)
    {
    	
    	return (a + b);
    }
    
    double add(double a, double b)
    {
    	
    	return (a + b);
    }

     

    测试二:C语言编译

    int add(int a, int b)
    {
    	return (a + b);
    }

     

    三、解决方案

    使用extern "C" {} ,让C++兼容C语言。这个是C++特有的符号,为了让编译器遵循C语言规则。

    测试:

    extern "C"
    {
    	
    int add(int a, int b)
    {
    	
    	return (a + b);
    }
    
    }
    

    编译出.o文件:g++ test.cpp -c -o test.o

    反汇编输出:objdump test.o -d > test.i

    结果:

    用g++编译输出的符号与C语言一样。

    这样,就解决了符号的问题。

    四、混合编程实验

    实验一:同一个项目全部有源码,一次编译链接

    //test.cpp
    
    #include <iostream>
    #include "clib.h"
    
    using namespace std;
    int main()
    {
    	int result;
    	
    	result = add(1.1,2.0);
    	
    	cout << "result: " << result << endl;
    	
    	return 0;
    }
    //clib.c
    
    #include "clib.h"
    
    int add(int a, int b)
    {
    	return (a + b);
    }
    //clib.h
    
    #ifndef __MYLIB_H
    #define __MYLIB_H
    
    #ifdef __cplusplus        //g++编译器会定义这个宏,而gcc没有
    extern "C"
    {
    #endif
    
    int add(int a, int b);
    
    
    
    #ifdef __cplusplus
    }
    #endif
    
    
    #endif

    实现同一个项目全部有源码,一次编译链接的方式是

    g++ test.cpp clib.c clib.h -o test

    这样的编译肯定没问题,但存在一个大问题:c文件被当作c++源码来编译了(因为c++是c的超集),c语言原本的编译高效就没了,况且有时候项目的某些源码就是用c语言来编写,遵循C语言编译规则比较好。

    那么怎么处理?

    用gcc单独编译 c文件,最后用g++全部链接在一起。

    gcc  clib.c  -c  -o  clib.o

    g++  test.cpp  clib.o  -o  test 

    值得关注的一点是,在很多项目中,我们都能看到.h文件包含以下内容:

    #ifdef __cplusplus       
    extern "C"
    {
    #endif

    ...

    #ifdef __cplusplus
    }
    #endif

    这样做,是为了让.h文件在g++编译器中依旧按照C语言的规则来编译,最终链接时候匹配到C库。

     

    实验二:同一个项目中C是库,C++是源码,C++调用C

    生成一个静态库,这个库是C语言编写的。

    ar  r  libclib.a  clib.o

    然后,我们用test.cpp去链接libclib.a库。

    g++  test.cpp  -lclib -L.  -o  test

    编译成功。

    成功的原因是,test.cpp里包含的 clib.h文件中包含了 extern "C"。

    在这里,再引出一个问题,加入clib.h没有包含 extern "C"呢?

    也很好解决,在test.cpp里补上。

    #include <iostream>
    
    extern "C"
    {
    #include "clib.h"
    }
    
    using namespace std;
    int main()
    {
    	int result;
    	
    	result = add(1.1,2.0);
    	
    	cout << "result: " << result << endl;
    	
    	return 0;
    }

    五、最后

    c++想要调用c源码,但又是c源码遵循c编译器的规则,则要使用extern "C"。

    在这里插入图片描述

     

    展开全文
  • 【Cpp】C和C++混合编程

    2020-02-15 21:49:52
    Cpp是从C演变过来的,C有很多优秀成熟项目库,没必要在C++中重写,C++程序可以直接调用调用 庞大项目划分后一部分适合用C(底层),一部分适合用C++(中间层、上层) 1.2 混合编程的支撑 编译型程序的编译过程:...

    一、混合编程杂绪

    1.1 为什么需要混合编程

    1. Cpp是从C演变过来的,C有很多优秀成熟项目和库,没必要在C++中重写,C++程序可以直接调用调用
    2. 庞大项目划分后一部分适合用C(底层),一部分适合用C++(中间层、上层)

    1.2 混合编程的支撑

    1. 编译型程序的编译过程:源文件->目标(库)文件->可执行程序->镜像文件
    2. 任何编程语言执行时都必须是可执行程序,所以都必须先被编译成目标文件
    3. 混合编程的“混合”操作发生在链接这一步

    1.3 C++和C混合编程出现的问题

    C++和C都是编译型语言,互相混合相对容易。但是:C++支持函数名重载,而C不支持,因此编译器生成目标文件时,函数名在目标文件中的临时内部名称规则不同,导致链接时符号对不上,如下所示:

    创建测试文件:

        touch cadd.c cppadd.cpp add.h Makefile
    

    源文件和头文件的内容如下,其中cadd.cappadd.c的内容都是一致的,均是库函数中声明的函数的定义
    clipboard_20200215044304.png
    我们分别把.c源文件和.cpp源文件做成静态链接库然后把库进行反汇编

    dec:
    	objdump -d libcadd.a > libcadd.i
    	objdump -d libcppadd.a > libcppadd.i
    

    clipboard_20200215051018.png
    对比得到的反汇编文件,可以发现同一个函数分别在gccg++下编译后生成的二进制代码其实是一样的。而临时内部名称是不同的:在gcc中,函数名保持不变;而g++中,还在函数名后增加了参数类型(add -> addii),如下图所示:
    clipboard_20200215045941.png
    这时如果用一个.c文件和g++编译制作的静态库进行gcc编译链接或用一个.cpp文件和gcc编译制作的库进行g++编译链接都会链接错误:

    #include "add.h"
    int main(void)
    {
        int x = 1, y = 1;
        add(x, y);
        return 0;
    }
    

    clipboard_20200215053956.png
    这就是因为主函数#include "add.h"中的add(预编译时直接替换相关内容)与静态库中的add用了不同的编译环境,导致标文件中的临时内部名称不同所致无法正确链接!

    二、C和C++混合编程的解决方案

    通过前面的研究我们可以知道C和C++本质上是可以混合编程的,但是生成的中间符号名称不同,所以链接器在进行链接时会出问题,那如何解决呢?

    2.1 先谈谈__cplusplus

    __cplusplus是C++中预定义的一个标准宏,为长整型,其值为cpp标准的年月;在C中是未进行定义的,可以用来检测编译环境

    #include <stdio.h>
    
    int main(void)
    {
        #ifdef __cplusplus
        printf("G++ %ld.\n", __cplusplus);
        #else
        printf("GCC.\n");
        #endif
    
        return 0;
    }
    

    clipboard_20200215064211.png

    2.2 extern "C"{}

    使用extern "C"{}可以使{}中的内容用C的标准来编译,我们将1.3中的add.h中的内容改为:

    #ifndef __ADD_H__
    #define __ADD_H__
    
    extern "C"
    {
    
    int add(int a, int b);
    
    }
    
    #endif
    

    然后和cppadd.cpp一起制作成静态库然后反编译,我们可以发现虽然用的g++进行编译,反编译得到的文件中add的临时名称还是add,而不是_Z3addii
    clipboard_20200215065948.png

    2.3 解决方案

    通过2.2我们可以知道在C++的头文件中只要把函数的声明放在extern "C"{}的大括号范围之内,就可以让g++在编译这个函数时生成中间符号名时按照C的规则而不是按照C++的规则,所以这样的函数就可以和C的库进行共同链接。但是,在C语言中,extern "C"{}是未被定义的
    clipboard_20200215070522.png
    所以我们将__cplusplus和extern “C”{}结合使用,通常有以下两种情况:

    三、两种常见情况

    3.1 同一个项目中C是库,C++是源码,C++调用C

    这是最常见的情况,我们只需要在C的头文件中加上extern "C"的声明,在C++中直接包含头文件调用。后继直接用g++编译链接即可,如下所示(mian.cpp和C库均来自1.3):
    clipboard_20200215073447.png
    add.h中的内容更改如下:

    #ifndef __ADD_H__
    #define __ADD_H__
    
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    int add(int a, int b);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif
    

    return.sh中内容如下:

    #!/bin/sh
    
    g++ main.c -lcadd -L. -o main.elf
    ./main.elf
    echo $?
    

    根据结果我们可以看到程序进行了成功的编译、链接、执行:
    clipboard_20200215073854.png
    如果我们同时有C和Cpp的源码,我们也是只需要在C的.h库函数中加入__cplusplusextern "C"{},对于Cpp的.hpp文件不做任何改动,最后统一进行g++编译即可

    3.2 同一个项目中C++是库,C是源码,C调用C++

    如果我们只有C++库而源码是C,我们最后只能用gcc编译链接,这带来了很多麻烦:

    1. g++gcc的编译时符号差异
    2. c++支持很多c并不支持的特性,如函数重载

    而C++继承了C的所有特性,也就是说C编译时无法直接像C++一样使用特定的语句实现编译Cpp时按照C的规则。但是,我们可以用cpp写一层封装层,加上extern "C",用g++编译成静态库,这个时候我们在C源码中就可以直接调用我们的静态库,用gcc编译链接!

    我们还是使用1.3中制作的静态库,我们检查发现此时libcppadd.aadd的临时符号是_Z3addii
    clipboard_20200215080137.png
    我们制作封装层,创建文件

    touch cppaddwrapper.cpp cppaddwrapper.hpp
    

    其中,cppaddwrapper.hpp中的内容如下:

    #ifndef __CPP_ADDWRAPPER_HPP__
    #define __CPP_ADDWRAPPER_HPP__
    
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    int addwrapper(int a, int b);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif
    
    

    cppaddwrapper.cpp中的内容如下

    #include "add.hpp"
    #include "cppaddwrapper.hpp"
    
    int addwrapper(int a, int b)
    {
        add(a, b);
    }
    
    

    我们只需要在这个函数中对add进行调用即可,我们将封装层用g++ar制作成静态封装库,再进行反编译,结果如下:
    clipboard_20200215084644.png
    因为在addwrapper函数的声明中加了extern "C",故临时符号没有改变。由于用的是g++编译,而该头文件包含中的add.hppadd函数没有extern "C"声明,所以调用时使用的add的临时名称还是会变成_Z3addii,和静态库中的临时名称相匹配,所以在反汇编代码callq 1d <addwrapper+0x1d>中发生了跳转。第一个参数1d就是add函数的地址入栈,尖括号里面的是偏移地址,因为我们使用的是静态库,无需重定位,所以偏移地址也是0x1d

    这个时候,我们就可以在我们自己的c文件中直接调用静态封装库中的函数,和封装库一起用gcc进行链接了!如下建立测试文件夹,将头文件和静态库移入文件夹中:
    clipboard_20200215085510.png

    main.c中的测试代码如下:

    #include "cppaddwrapper.hpp"
    
    int main(void)
    {
        addwarpper(1, 1);
        return 0;
    }
    

    shell脚本中的内容如下:需要注意的是由于封装层的静态库是使用了C++库的,所以在链接的时候也需要用-lxx指定静态库

    #!/bin/sh
    
    gcc main.c -lcppaddwrapper -lcppadd -L. -o main.elf
    ./main.elf
    echo $?
    

    根据main函数的返回值我们可以知道程序成功地进行了编译链接执行
    clipboard_20200215085827.png
    在只有C++库而源码是C的情况下,使用封装层的技巧就是封装层使是用g++编译,但是只在封装头文件函数声明中加了extern "C",而调用的C++静态库函数的#include未加,因此调用的函数还是按C++的规则解析,制作库时可以实现连接。在C源码中调用封装库,巧妙避免了直接使用C++库由于临时符号不同导致的链接错误

    展开全文
  • 本文主要给大家介绍了关于C/C++混合编程extern “C”使用的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。 首先要明白: C++号称是C语言的超集,也确实,从语言的基本语法上,C++是...
  • Qt在当下嵌入式开发中越来越热,而QML的引入,开辟了界面功能解耦开发的先河,这份资料系统介绍了Qt QML开发技术,详细说明了C++ QML如何交互,推荐给大家一起学习。
  • 这篇文章讲解的知识点很“小”,但是在C和C++混合编程中非常重要。 因为我们在写应用程序时,经常利用到第三方的程序。 如果我们的代码用C,但是第三方代码是C++; 或者我们的代码用C++,而第三方的代码是C, ...

     这篇文章讲解的知识点很“小”,但是在C和C++的混合编程中非常重要。

    因为我们在写应用程序时,经常利用到第三方的程序。

    如果我们的代码用C,但是第三方代码是C++;

    或者我们的代码用C++,而第三方的代码是C,

    那么在整合的时候就需要仔细一点了。

    一、C调用C++中的函数

    1. 被调用C++代码中的头文件(callee.h)

     

    2. 被调用C++代码中的源文件(callee.cpp)

     

    3. 被调用C++代码编译成目标文件(callee.o)

     

    知识点:

    (1)关于 __cplusplus

        编译器使用g++,所有的C++编译器中都会定义宏:__cplusplus,因此在编译callee.h的时候,会把函数声明包裹在extern "C" 中。

     

    (2)关于 extern "C"

        C和C++编译器,在编译一个函数的时候,编译策略是不同的。C++会对函数的名称进行改写(而且每个C++编译器对于名字改写的规则也是不一样的,甚至同一个编译器的不同版本的名字改写规则也不一样,因此,使用C++时最好用相同的编译器版本对项目中的所有模块进行编译。补充:改写的目的是为了实现C++语言中的函数重载)。

        在callee.h中,把函数 cpp_hello 放在 extern "C" 中,意思就是告诉编译器g++: 这个函数是需要被C调用的,请不要对这个函数进行名字改写。

        可以通过 nm 指令查看一下目标文件callee.o中的符号:

        我们可以多做一个测试:把extern "C"去掉之后,看一下这个函数如何被g++改写了名字:

    4. 主调用C代码中的源文件(caller.c)

     

    5. 编译主调用C文件,得到可执行文件

     

    知识点:

    (1)caller.c在 include “callee.h" 时,gcc编译器中没有定义 __cplusplus 宏,所以 callee.h 中就相当于只有一句话:void cpp_helo();

     

    (2)在调用 cpp_hello()函数时,虽然这个函数是用g++编译的,但是由于使用了 extern "C",所以名字没有被编译器g++改写,也就是说,在callee.o目标文件中,函数的名字就是 "cpp_hello",所以可以顺利的被C代码调用到。

     

    二、C++调用C中的函数

    1. 被调用C代码中的头文件(callee.h)

     

    2. 被调用C代码中的源文件(callee.c)

     

    3. 被调用C代码编译成目标文件(callee.o)

     

    知识点:

        编译器使用gcc,其中没有定义宏:__cplusplus,因此在编译callee.h的时候,相当于只有一个函数声明。因此函数c_hello在被编译到callee.o目标文件中时,没有被改名。

     

    4. 主调用C++代码源文件(caller.cpp)

     

    5. 编译主调用C++文件,得到可执行文件

     

    知识点:

        g++在编译callee.h时,由于g++中定义了__cplusplus宏,因此它在调用函数 c_hello时,就会按照C的方式去调用(也就是没有名字改写),所以就能顺利的在callee.o中查找到这个函数。

     

    三、总结

    1. 在C++代码的函数声明时,如果代码会被C程序调用,一定要加上 extern "C"。

    2. 在C代码的函数声明时,如果代码会被C++程序调用,也要加上extern "C"。

    3. 在用C++编程时,最好各模块统一使用相同的编译器,包括版本最好也相同。

     

    不知道这篇博文对你有没有帮助呢?

    原创不易,希望大家多多支持,评论和点赞都是免费的哦~~~

    展开全文
  • c和c++混合编程

    2021-01-28 11:42:49
    编译器类型: 1.c中:gcc 2.c++中:g++ 格式: 1.包含必要的头文件 2.使用宏定义(在头文件中): # if _ _cplusplus ...ubuntu下混合编程: gcc -c fun.c -o fun.o g++ main.cpp fun.o -o main 例子: ...
    • 编译器类型:
      1.c中:gcc
      2.c++中:g++
    • 格式:
      1.包含必要的头文件
      2.使用宏定义(在头文件中):
    #if __cplusplus
    extern "C" {
       
    #endif
        函数的一些声明......;
    #if __cplusplus
    }
    
    展开全文
  • MATLAB与C语言混合编程示例,高清电子版PDF教程,十分适合入门新手快速掌握两种语言的切换与联调
  • C和C++混合编程

    2016-08-14 19:54:38
    本文系统讲解了C和C++混合编程的部分知识,涉及知识点如下: 1、#ifdef _cplusplus/#endif _cplusplus及发散 2、extern "C" 2.1、extern关键字 2.2、"C" 2.3、小结extern "C" 3、C和C++互相调用 4、C和C++混合调用...
  • C C++ 混合编程

    千次阅读 2012-02-23 16:12:02
    在最近的arm开发中,因为一些特定的...参考网上的一些资料,本文1将相关的知识点简要总结如下:c&c++混合编程的注意事项,在c++函数中调用c函数的方法,在c函数中调用c++函数的方法,在c函数中调用C++对象及其中
  • 这就像人们用Android Studio(或者Eclipse等)开发Android应用程序时可用写C++程序一样。默认情况下,Qt只能用Qt提供的模块(大多数情况下已经够用了)写C++程序。但是,在一些特定的情况下你需要用到一些Android ...
  • 实验表明,给出的Matlab与C/C++混合编程接口及应用方法是有效、实用的。  1 引言  Matlab 是当前应用最为广泛的数学软件,具有强大的数值计算、数据分析处理、系统 分析、图形显示甚至符号运算等功能[1]。利用这...
  • C/C++混合编程

    2019-04-24 19:35:55
    混合使用C++和C代码是实际工程中不可避免的,虽然C++编译器能够兼容C语言的编译方式,但C++编译器会优先使用C++的方式进行编译。利用extern "C" 关键字可以强制让C++编译器以C的方式进行编译。 2. C和C++的编译规则...
  • MPI与OpenMP并行程序设计:C语言
  • C++C语言混合编程

    千次阅读 2017-11-04 21:56:41
    之前一直以为C++和C语言是一样的,可以很方便的互相调用,昨天想把一个C语言项目编译到C++语言的项目中时才发现,C语言和C++还是有一定区别的,最少互相之间的调用并不像想象中的那么简单。在网上找到了一些资料作为...
  • 关于keil中的c语言和c++混合编程

    千次阅读 2017-12-29 16:56:11
    c语言编程简单,但是对于编写面向对象来说...所以在工程中使用c语言和c++混合编程是非常又必要的。 第一步先设置一下keil的c++编译环境,只需设计下面一步即可。 a.h文件: #ifndef _A_ #define _A_ voi
  • 如只想知道怎样就能实现C/C++混合编程而不深究为什么的话, 可以一拉到底直接看总结. 首先, 在介绍C/C++混合编程之前, 先思考几个问题 C/C++混合编程是什么? C/C++混合编程有什么用? C/C++混合编程应该怎么实现...
  • 实验表明,给出的Matlab与C/C++混合编程接口及应用方法是有效、实用的。  1 引言  Matlab 是当前应用为广泛的数学软件,具有强大的数值计算、数据分析处理、系统 分析、图形显示甚至符号运算等功能[1]。利用这一...
  • 本文主要介绍C/C++在Java、AndroidObjective-C三大平台下实现混合编程,这里举例说明实现不同平台用C/C++实现编程的方法,有兴趣的小伙伴可以参考下
  • C和C++混合编程的Makefile的编写!

    万次阅读 2014-07-26 18:57:46
    在项目实践中,经常遇到C和C++混合编程的情况。
  • Matlab与C_C++混合编程技术

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 46,382
精华内容 18,552
关键字:

c和c++混合编程

c++ 订阅