linux下c/c++混合编程

一. 知识储备:

         linux下c++用的编译器是g++,而编译c程序中用的编译器是gcc,编译出来的obj文件肯定是不一样的,但是c++是兼容c的,所以c++文件是可以编译成兼容c的代码,比如

//1.cpp
#include <iostream>
using namespace std;
void test()
{
}
1.cpp编译成.o文件==> g++ -c 1.cpp

 nm 1.o

         U __cxa_atexit
         U __dso_handle
00000044 t _GLOBAL__sub_I__Z4testv
00000005 t _Z41__static_initialization_and_destruction_0ii
00000000 T _Z4testv //这里 test函数经过g++编译之后(没链接之前),将函数test进行了修饰,即 test前面加上了_Z4,后面加上v(即void 参数),若test函数中的参数是int型变量,则编译之后应该为 _Z4testi(i为int行)
         U _ZNSt8ios_base4InitC1Ev
         U _ZNSt8ios_base4InitD1Ev
那么如果是.c文件编译成.o文件会如何呢?

#include <stdio.h> //1.c
void test()
{
}
1.c编译成.o文件==> gcc -c 1.c

nm 1.o

00000000 T test //这里直接就用函数名
通过上面我们可以看出原来c++的函数的重载实质就是这样啊,编译器偷偷的将函数名进行了修饰。。。。

那么c++如何才能编译成c的那样的函数名呢?====> 即用 extern "C"

#include <iostream> //1.cpp
using namespace std;
extern "C" //修饰 test,告诉编译器编译的时候以c编译器的编译规则来编译
void  test()
{

}
之后 g++  -c  1.cpp

nm 1.o

         U __cxa_atexit
         U __dso_handle
00000044 t _GLOBAL__sub_I_test
00000000 T test //发现编译之后只是test函数
00000005 t _Z41__static_initialization_and_destruction_0ii
         U _ZNSt8ios_base4InitC1Ev
         U _ZNSt8ios_base4InitD1Ev
00000000 b _ZStL8__ioinit

一.  c++提供接口给c程序用:

//func.h
#include <iostream>
using namespace std;
class func
{
public:
    int add(int num1, int num2);
}

//func.cpp
#include "func.h"
int func::add(int num1, int num2) //这里前面不需要加extern "C",因为func::add 这种写法无法编译成c形势的,因为他本来就是c++的写法,
{   cout<<"helo"<<endl;
    return num1 + num2;
};

上面是c++ 类,用来进行计算的一个类,它提供了加法的接口,我们可以做一个接口来给c程序用

//interface.cpp
#include "func.h"
extern "C"
int interface(int num1, int num2)//这里告诉g++编译的时候函数名为interface,而不是修饰之后的c++形式
{
   func add_class;
   return add_class.add(num1, num2);
}

   介绍三种方法: ①.直接链接使用, ②.动态库, ③.静态库

调用接口的代码:

#include <stdio.h> //main.c
extern  int interface(int num1, int num2);
int main()
{
int i = interface(2, 3);
printf("[%d]\n", i);
    return 0;
}

 ①直接链接使用:

    g++ -c  func.cpp

    g++ -c interface.cpp

    gcc -c main.c

 之后都变成了 .o文件,所以在连接的时候 main函数就会链接到interface符号,即可以链接上了,而interface中代码之后的add_class都是c++形势编译的,所以能链接上

 func, 而func中调用c++中的库cout等等,所以要链接 -lstdc++这个动态库

    gcc -o main func.o interface.o main.o  -lstdc++

②.动态库

    g++ -fpic -c interface.cpp

    g++ -fpic -c func.cpp

    g++ -shared -o libadd.so interface.o func.o (-lstdc++) //其实这里g++自动进行了动态库stdc++动态库的链接操作,动态库创建完后可查看动态库链接信息,命令是readelf -d     libadd.so

  标记        类型                         名称/值
 0x00000001 (NEEDED)                     共享库:[libstdc++.so.6]
 0x00000001 (NEEDED)                     共享库:[libgcc_s.so.1]
 0x00000001 (NEEDED)                     共享库:[libc.so.6]
我们在查看一下内部的接口信息: nm libadd.so

000007eb T interface //发现有我们调用的接口信息
之后: gcc -o main main.c -L. libadd.so
注意这个是链接阶段,还有执行阶段,我比较懒,就 cp libadd.so /lib/

③.静态库

    g++ -c interface.cpp

    g++ -c func.cpp

    ar rv libadd.a interface.o func.o

    gcc -o main main.c libadd.a -lstdc++ //注意要加上 -lstdc++,静态库只是把两个.o弄在一起,并且这里链接阶段如同第一种方法,cout需要库,所以要加上-lstdc++,而动态库的方法就不需要,因为g++生成的动态库编译器默认就链接上了stdc++这个库

二.  c提供接口给c程序用:

其实很简单,与上面是一样得,在c++文件中extern c程序的接口前加上extern "C"

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本资源为arm-linux下的海思编译链工具V300 C语言有三种标准库如下: 1.Glibc glibc = GNU C Library 是GNU项(GNU Project)目,所实现的 C语言标准库(C standard library)。 目前,常见的桌面和服务器中的GNU/Linux类的系统中,都是用的这套C语言标准库。 其实现了常见的C库的函数,支持很多种系统平台,功能很全,但是也相对比较臃肿和庞大。 2.uClibc 一个小型的C语言标准库,主要用于嵌入式。 其最开始设计用于uClinux(注:uClinux不支持MMU),因此比较适用于微处理器中。 对应的,此处的u意思是μ,Micro,微小的意思。 uClibc的特点: (1)uClibc比glibc要小很多。 (2)uClibc是独立的,为了应用于嵌入式系统中,完全重新实现出来的。和glibc在源码结构和二进制上,都不兼容。 3.EGLIBC EGLIBC = Embedded GLIBC EGLIBC是,(后来)glibc的原创作组织FSF所(新)推出的,glibc的一种变体,目的在于将glibc用于嵌入式系统。 EGLIBC的目标是: (1)保持源码和二进制级别的兼容于Glibc 源代码架构和ABI层面兼容 如果真正实现了这个目标,那意味着,你之前用glibc编译的程序,可以直接用eglibc替换,而不需要重新编译。 这样就可以复用之前的很多的程序了。 (2)降低(内存)资源占用/消耗 (3)使更多的模块为可配置的(以实现按需裁剪不需要的模块) (4)提高对于交叉编译(cross-compilation)和交叉测试(cross-testing)的支持 【目前了解到的海思交叉编译工具链的应用环境】 arm-hisiv100-linux为基于uclibc的工具链,arm-hisiv200-linux 为基于 glibc 的工具链; arm-hisiv300-linux为基于uclibc的工具链,arm-hisiv400-linux 为基于 glibc 的工具链; arm-hisiv500-linux为基于uclibc的工具链,arm-hisiv600-linux 为基于 glibc 的工具链。 (在开发的时候,你编译内核所用的交叉编译链跟用户的应用程序所用的交叉编译链一定需要相同,不然没法调用系统内核的依赖库)   其中eglibc这种很容易被人开发者忽视,从而选错了编译工具链。 uClibc和Glibc并不相同,两者有许多不同之处,有可能给你带来一些问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值