c++,extern “c”

时间:2022-09-29 17:12:57

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!\n");
} //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(,);
cout<<"2+3="<<i<<endl; sayHello();
return ;
}

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

#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(,) ;
printf("2+3 = %d\n", i); return ;
}
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
+ =

参考:

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

c++,extern “c”的更多相关文章

  1. C&sol;C&plus;&plus;&colon;C&plus;&plus;中static,extern和extern &quot&semi;C&quot&semi;关键字

    1. extern 变量 extern 表明该变量在别的地方已经定义过了,在这里要使用那个变量. 当extern不与"C"在一起修饰变量或函数时,如在头文件中: extern in ...

  2. C&plus;&plus;11老关键字的新含义&lpar;auto&comma; using,extern&rpar;

    http://blog.csdn.net/cnsword/article/details/8034947 公司可以使用c++11.看大牛的代码模仿使用,所以现在已经不知道什么使用的是c++的语法还是c ...

  3. DLL模块例2:使用&lowbar;&lowbar;declspec&lpar;dllexport&rpar;导出函数,extern &quot&semi;C&quot&semi;规范修饰名称,隐式连接调用dll中函数

    以下内容,我看了多篇文章,整合在一起,写的一个例子,关于dll工程的创建,请参考博客里另一篇文章:http://www.cnblogs.com/pingge/articles/3153571.html ...

  4. 全局变量,extern和static以及命名空间的区别

    全局变量,extern和static以及命名空间的区别        全局变量只是在声明它的文件中有效,假如在另一个文件中声明定义了一个相同名称的全局变量,则在后续使用这两个变量的时候会产生名字上的冲 ...

  5. 多文件协作,extern、static、头文件

    多个cpp文件协同工作.使用外部函数.变量时,必须先声明再使用.声明外部函数(一般在main.cpp中),extern可省略(主函数中默认可访问外部函数)extern void RectArea(); ...

  6. c调用c&plus;&plus;编的dll,c&plus;&plus;调用c编写的dll,extern &OpenCurlyDoubleQuote;C”的用法

    转自:http://blog.csdn.net/life_is_too_hard/article/details/52137271 c和c++不能直接相互调用,主要是因为c++有重载函数的功能,为了区 ...

  7. &lpar;转&rpar;C&sol;C&plus;&plus;——auto,static,register,extern用法

    转自:https://blog.csdn.net/u010757264/article/details/49932829 C++中变量.函数的属性包括数据类型和存储类别.存储类别分为静态存储和动态存储 ...

  8. C&plus;&plus;中static,extern和extern &quot&semi;C&quot&semi;关键字

    1. extern 变量 extern 表明该变量在别的地方已经定义过了,在这里要使用那个变量. 当extern不与"C"在一起修饰变量或函数时,如在头文件中: extern in ...

  9. C、C&plus;&plus;编译,链接,extern链接

    //b.cpp #inlcude <iostream> void b() { std::cout<<"fun b"; } //a.cpp extern vo ...

  10. gcc,g&plus;&plus;,extern &OpenCurlyDoubleQuote;C” :一些编译错误的缘由

    正好是我们代码中遇到的问题,之前不求甚解,只用g++编译没有错误就不管了,现在要跨平台到windows下就遇到了问题.全文转载自:http://user.qzone.qq.com/75172588/b ...

随机推荐

  1. Bootstrap响应式栅格系统的设计原理

    1.历史背景 Bootstrap是Twitter的工程师Mark Otto和Jacob Thornton开发的一套供内部使用的UI框架,于2011年开源.2012年发布的第二版中新增了12列栅格系统和 ...

  2. xpath实例 --&sol;&sol;span&lbrack;contains&lpar;&period;&comma;&&num;39&semi;资讯管理&&num;39&semi;&rpar;&rsqb;

    实际例子: 实例一: 不得不说下第一个例子,谢谢selenium论坛的大神门,XPATH还有这种方式的定位,传说是“治疗一切跌打损伤,及text找不到”(Antony群友帮解决的,在此谢谢)

  3. js将数字转换成大写的人民币表达式

    function changeNumMoneyToChinese(money) { var cnNums = new Array("零", "壹", &quot ...

  4. Angularjs&comma;WebAPI 搭建一个简易权限管理系统

    Angularjs,WebAPI 搭建一个简易权限管理系统 Angularjs名词与概念(一)   1. 目录 前言 Angularjs名词与概念 权限系统原型 权限系统业务 数据库设计和实现 Web ...

  5. java System&period;currentTimeMillis&lpar;&rpar;毫秒值和具体日期值互相转换

    System.currentTimeMillis()与日期 间是可以相互转换的,通过 SimpleDateFormat dateformat = new SimpleDateFormat(" ...

  6. JavaScript 基本语法结构

    1 变量 JavaScript的变量是弱类型的,就是所有的对象都是使用var 来进行声明 2 变量的命名规则 1.由字母.数字.下划线组成,区分大小写 2.以字母开头 3.变量名不能有空格 4.不能使 ...

  7. 【Unity】透明度渐变

    写给美术大佬的脚本,还要继续改,github地址:TransEffect[github] 效果图如下: Ver.1源码,针对3d Object: using System.Collections; u ...

  8. python3 int(整型)

    __abs__(返回绝对值) n = -5 print(n.__abs__()) #输出:5 __add__(相加,运算符:+) n = 3 print(n.__add__(5)) #输出:8 __a ...

  9. 关于final static修饰的常量部署后没有更新的问题

    出现问题的场景是这样的: 项目中有个专门放流程Key值常量的类FlowConstants.java,其中这些常量都用了final static 修饰.某天因为修改了流程,相应的key值也改变了,所以直 ...

  10. cocos2d-x学习记录2——CCAction动作

    CCAction能够使CCNode运动起来,能够呈现出多种多样的动作.这些动作能够改变其运动方向.形状.大小.旋转等. 同时,还可利用CCCallFunc.CCCallFuncN.CCCallFunc ...