• 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”)。

    1.如果要在C++程序中调用C语言写的函数, 在C++程序里边用 extern "C" 修饰要被调用的这个C程序,告诉C++编译器此函数是C语言写的,是C语言编译器生成的,调用他的时候请按照C语言习惯传递参数等。例子如下:

      首先我们有C语言制作的函数库:libmyclib.a (参考gcc生成静态库和动态库[1]

        gcc -c clib_hello.c clib_math.c

        ar -r libmyclib.a *.o

    //clib_hello.c
    #include <stdio.h>
    void sayHello(void)
    {
        printf("clib hello!
    ");
    }
    
    //clib_math.c
    int add(int va ,int vb)
    {
        return va+vb;
    }
    
    //clib_hello.h
    extern void sayHello(void);
    
    //clib_math.h
    extern int add(int va ,int vb);

      

      然后,cpp编译链接c函数库 

        g++ cppMain.cpp libmyclib.a -o democpp

        【或者:g++ cppMain.cpp -L. -lmyclib】

    //cppMain.cpp
    
    #include <iostream>
    using namespace std;
    #if 0  
    extern "C"{////可以,但不推荐。 《华为技术有限公司c语言编程规范》 规则1.8 禁止在extern "C"中包含头文件。
        #include "clib_hello.h"
        #include "clib_math.h"
    }
    #endif
    extern "C" void sayHello(void);
    extern "C" int add(int va ,int vb);
    
    //extern void sayHello(void);
    //extern int add(int va ,int vb);//编译错误,undefined reference to `xxx()'
    
    int main()
    {
        int i =  add(2,3);
        cout<<"2+3="<<i<<endl;
    
        sayHello();
        return 0;
    }

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

    #ifdef __cplusplus
    extern "C" {
    #endif
    
    //....头文件主体部分
    void    cfree();
    int     malloc_trim();
    //....
    
    #ifdef __cplusplus
    };  /* end of extern "C" */
    #endif

    这样的结构保证了该头文件可以被cpp或者c程序使用,

    如果#ifdef  __cplusplus,  头文件主体成为extern "C"{......},保证可被cpp使用。

    如果#ifndef  __cplusplus,  头文件主体为 ...... ,保证可被c使用。

      也有这样的方法:

    #ifdef __cplusplus
    #define CPP_ASMLINKAGE        extern "C"
    #else
    #define CPP_ASMLINKAGE
    #endif
    
    #define asmlinkage CPP_ASMLINKAGE
    
    ....
    asmlinkage void resume(void);
    asmlinkage void free(void);
    ....

    2.假如希望c++中定义的函数能被c引用,则加上extern "C";

    //cpplib_math.cpp
    extern "C" int add(int a ,int b)
    {
        return a+b;
    }
    
    //cMain.c
    #include <stdio.h>
    extern int add(int a,int b);
    //extern "C" int add(int a,int b);//c中不能有这样的表达式
    int main()
    {
        int i = add(2,3) ;
        printf("2+3 = %d
    ", i);
        
        return 0 ;
    }
    root@ubuntu:~/Desktop/ work/demo/cpplib# g++ -c cpplib_math.cpp 
    
    root@ubuntu:~/Desktop/ work/demo/cpplib# ar -r libcpplib_math.a cpplib_math.o
    ar: creating libcpplib_math.a
    
    /*
    root@ubuntu:~/Desktop/ work/demo/cpplib# gcc cMain.c -o cExe -L. -lcpplib_math
    ./libcpplib_math.a(cpplib_math.o):(.eh_frame+0x12): undefined reference to `__gxx_personality_v0'   
    用 gcc 连接 C++ 程序也可以,但是需要人为指定连接 C++ 标准库.[4]
    */
    root@ubuntu:~/Desktop/ work/demo/cpplib# gcc cMain.c -o cExe -L. -lcpplib_math -lstdc++
    
    root@ubuntu:~/Desktop/ work/demo/cpplib# l
    cExe*  cMain.c  cpplib_math.cpp  cpplib_math.o  libcpplib_math.a
    
    root@ubuntu:~/Desktop/ work/demo/cpplib# ./cExe 
    2+3 = 5
    
    

    参考:

    1. gcc生成静态库和动态库 http://blog.chinaunix.net/uid-17267213-id-3057974.html

        gcc创建和使用静态库、动态库  http://www.cnblogs.com/dyllove98/archive/2013/06/25/3155599.html

    2. extern "C"的用法解析  http://www.cnblogs.com/rollenholt/archive/2012/03/20/2409046.html

    3.C中如何调用C++函数  http://www.cppblog.com/franksunny/archive/2007/11/29/37510.html

    4. 错误:undefined reference to `__gxx_personality_v0'      http://blog.csdn.net/dycwahaha/article/details/2636382

  • 相关阅读:
    第11周学习进度条
    人月神话阅读笔记03
    人月神话阅读笔记02
    第10周学习进度条
    对各团队的评价意见
    第九周学习进度条
    《构建之法阅读笔记05》
    站立会议10
    第十一周学习进度
    cnblogs.com的用户体验
  • 原文地址:https://www.cnblogs.com/mylinux/p/4173877.html
Copyright © 2020-2023  润新知