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!\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”的更多相关文章
- C/C++:C++中static,extern和extern "C"关键字
1. extern 变量 extern 表明该变量在别的地方已经定义过了,在这里要使用那个变量. 当extern不与"C"在一起修饰变量或函数时,如在头文件中: extern in ...
- C++11老关键字的新含义(auto, using,extern)
http://blog.csdn.net/cnsword/article/details/8034947 公司可以使用c++11.看大牛的代码模仿使用,所以现在已经不知道什么使用的是c++的语法还是c ...
- DLL模块例2:使用__declspec(dllexport)导出函数,extern "C"规范修饰名称,隐式连接调用dll中函数
以下内容,我看了多篇文章,整合在一起,写的一个例子,关于dll工程的创建,请参考博客里另一篇文章:http://www.cnblogs.com/pingge/articles/3153571.html ...
- 全局变量,extern和static以及命名空间的区别
全局变量,extern和static以及命名空间的区别 全局变量只是在声明它的文件中有效,假如在另一个文件中声明定义了一个相同名称的全局变量,则在后续使用这两个变量的时候会产生名字上的冲 ...
- 多文件协作,extern、static、头文件
多个cpp文件协同工作.使用外部函数.变量时,必须先声明再使用.声明外部函数(一般在main.cpp中),extern可省略(主函数中默认可访问外部函数)extern void RectArea(); ...
- c调用c++编的dll,c++调用c编写的dll,extern “C”的用法
转自:http://blog.csdn.net/life_is_too_hard/article/details/52137271 c和c++不能直接相互调用,主要是因为c++有重载函数的功能,为了区 ...
- (转)C/C++——auto,static,register,extern用法
转自:https://blog.csdn.net/u010757264/article/details/49932829 C++中变量.函数的属性包括数据类型和存储类别.存储类别分为静态存储和动态存储 ...
- C++中static,extern和extern "C"关键字
1. extern 变量 extern 表明该变量在别的地方已经定义过了,在这里要使用那个变量. 当extern不与"C"在一起修饰变量或函数时,如在头文件中: extern in ...
- C、C++编译,链接,extern链接
//b.cpp #inlcude <iostream> void b() { std::cout<<"fun b"; } //a.cpp extern vo ...
- gcc,g++,extern “C” :一些编译错误的缘由
正好是我们代码中遇到的问题,之前不求甚解,只用g++编译没有错误就不管了,现在要跨平台到windows下就遇到了问题.全文转载自:http://user.qzone.qq.com/75172588/b ...
随机推荐
- Implement custom foreach function in C#
http://msdn.microsoft.com/en-us/library/System.Collections.IEnumerator.aspx http://support.microsoft ...
- exists
select count(*) from Table_A where exists (select count(*) from Table_B.Column1 = Table_A.Column1) 该 ...
- javascript对象属性——数据属性和访问器属性
ECMA-262第五版在定义时,描述了属性property的各种特征,定义这些特性是为了实现javascript引擎用的,为了表示该特性是内部值,规范把它们放在了两对儿方括号中,例如[[Enumera ...
- 基本的编程原则SOLID
1.单一职责原则:每个类只负责完成一个职责,当它需要完成多个职责时就需要将它拆分开来. 2.开放封闭原则:对扩展开放,对修改封闭. 3.里氏替换原则:子类对象可以替换(代替)它的所有父类(超类)对象. ...
- .net 中实现php rawurlencode方法(RFC3986)
在对接api时候,经常需要对字符串进行各种编码处理,系统可能是异构的,实现语言也就可能是不一样的.所以经常会使人犯一些2B的错误! 比如:php实现的api中用了rawurlencode,文档中写,需 ...
- ThinkPHP第四天(U函数,URL类型参数配置,伪静态后缀名配置,数据传递与获取$_GET等)
1.U('地址','参数','伪静态','是否跳转','是否显示域名'); 在模板中使用U方法而不是固定写死URL地址的好处在于,一旦你的环境变化或者参数设置改变,你不需要更改模板中的任何代码. 在模 ...
- YII2 使用js
1.在 /backend/assets/ 中新建一个文件 CollectionAsset.php <?php /** * @link http://www.yiiframework.com/ * ...
- MYSQL 好文章集锦
比较细致的讲解MySQL数据库的数据结构以及实现原理 MySQL索引背后的数据结构及算法原理 MySQL的InnoDB索引原理详解 MySQL索引原理及慢查询优化 持续更新,快乐学习.
- eval以及json
参考 http://www.cnblogs.com/artwl/archive/2011/09/07/2169680.html http://www.cnblogs.com/objectorl/arc ...
- QT学习 之 文本文件读写
上一章我们介绍了有关二进制文件的读写.二进制文件比较小巧,却不是人可读的格式.而文本文件是一种人可读的文件.为了操作这种文件,我们需要使用QTextStream类.QTextStream和QDataS ...