转载于:http://blog.csdn.net/lincoln_2012/article/details/50801080

  项目中经常使用C和C++混合编程,那么,在调用对方接口时,总是不可避免地出现问题。为了让双方和谐地工作,就得用到extern "C"。

1 问题

在C++中,为了支持重载机制,在编译时,要对函数的名字进行一些处理,比如加入函数的返回类型等来加以区别;在C中,只是简单的函数名字而已。如函数void func(int i),C++会把它编译成类似_fun_int或_xxx_funIxxx这样的增加了参数类型的符号,这也是C++可以实现重载的原因;C则把该函数编译成类似_fun的符号,C链接器只要找到该函数符号就可以链接成功,它假设参数类型信息是正确的。故而,关键问题是,C和C++在编译时生成函数名字的方式是不同的。

2 方法

extern
"C"是C++的特性,是一种链接约定,它并不影响调用函数的定义,即使做了该声明,对函数类型的检查和参数转换仍要遵循C++的标准,而不是C。主要是为了解决C++在调用C函数库时,用C++直接链接就会出现不能识别符号的问题,而用上extern
"C"后,告诉C++编译器要以C语言的方式编译和链接函数,即直接使用函数名而不是一个经过处理的函数名。

3 示例

3.1 C++中调用C接口

代码:

  1. /***** C头文件c.h *****/
  2. #ifndef  _C_H_
  3. #define _C_H_
  4. #ifdef __cplusplus    /*C++编译器包含的宏,例如用g++编译时,该宏就存在,则下面的语句extern "C"才会被执行*/
  5. extern "C" {          /*C++编译器才能支持,C编译器不支持*/
  6. #endif
  7. void C_fun();
  8. #ifdef __cplusplus
  9. }
  10. #endif
  11. #endif
  1. /***** C源文件c.c *****/
  2. #include "c.h"
  3. void C_fun()
  4. {
  5. /*dosomething*/
  6. }
  1. 功能:在文件cpp.cpp中调用文件c.c中的函数C_fun()
  2. /****** C++源文件cpp.cpp ******/
  3. #include "c.h"
  4. int main()
  5. {
  6. C_fun()
  7. }

编译: g++ cpp.cpp c.c

3.2 C中调用C++接口

代码:

  1. /**** C++头文件 cpp.h *****/
  2. #ifndef  CPP_H
  3. #define CPP_H
  4. extern "C" int add( int x, int y );
  5. #endif
  1. /**** C++源文件 cpp.cpp *****/
  2. #include "cpp.h"
  3. int add( int x, int y )
  4. {
  5. return x + y;
  6. }
  1. 功能:C文件中调用C++的接口
  2. /**** C源文件c.c *****/
  3. extern int add( int x, int y );
  4. int main( int argc, char* argv[])
  5. {
  6. }

编译:gcc c.c cpp.cpp

3.3 C++中调用C库的函数

代码:

  1. /*C库源文件: hello.c*/
  2. #include <stdio.h>
  3. void func()
  4. {
  5. printf("hello,world!\n");
  6. }

编译:gcc --shared -o libhello.so hello.c

  1. /*C++源文件test.cpp中调用C库的函数*/
  2. #include <iostream>
  3. #ifdef __cplusplus
  4. extern "C" {               // 告诉编译器下列代码要以C链接约定的模式进行链接
  5. #endif
  6. void func();
  7. #ifdef __cplusplus
  8. }
  9. #endif
  10. int main()
  11. {
  12. func();
  13. return 0;
  14. }

编译:g++ test.cpp -o test -lhello

3.4 C中调用C++库的函数

1)C++库代码

  1. /*C++库源文件hello.cpp*/
  2. #include <iostream>
  3. void funcpp()
  4. {
  5. std::cout << "hello, world" << std::endl;
  6. }

编译:g++ --shared -o libhello.so hello.cpp
2)中间接口库,对C++库进行二次封装

  1. /*中间接口库 mid.cpp*/
  2. #include <iostream>
  3. void funcpp();
  4. #ifdef __cplusplus
  5. extern "C" {  // 即使这是一个C++程序,下列这个函数的实现也要以C约定的风格来搞!
  6. #endif
  7. void m_funcpp()
  8. {
  9. funcpp();
  10. }
  11. #ifdef __cplusplus
  12. }
  13. #endi

编译:g++ --shared -o libmid.so mid.cpp -lhello
3)C通过链接二次接口库调用C++库

  1. /*C源文件test.c*/
  2. #include <stdio.h>
  3. int main()
  4. {
  5. m_funcpp();
  6. return 0;
  7. }

编译:gcc test.c -l mid -o test

最新文章

  1. CSS权威指南之css声明,伪类,文本处理--(简要笔记一)
  2. Hadoop系列教程&lt;一&gt;---Hadoop是什么呢?
  3. java中常见的几种Runtimeexception
  4. java上传xls文件
  5. 斯坦福第十九课:总结(Conclusion)
  6. 使用GROUP BY统计记录条数 COUNT(*) DISTINCT
  7. leetcode 112 Path Sum ----- java
  8. java中的匿名内部类
  9. hdu1026 Ignatius and the Princess I (优先队列 BFS)
  10. javascript中,数组常用的方法有哪些?
  11. 百度地图 Android SDK - 个性化地图
  12. H5编辑器核心算法和思想-遁地龙卷风
  13. 自动化测试基础篇--Selenium多窗口、句柄问题
  14. WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable Exception in thread &quot;main&quot; java.io.IOException: No FileSystem for sc F
  15. linux 的基本操作(编写shell 脚本)
  16. ES6 数组
  17. 读取HTML文件进行格式化解析
  18. 关于C# winform怎么调用webapi来获取到json数据
  19. 2017-2018 Exp4 恶意代码分析 20155214曾士轩
  20. React中的的JSX

热门文章

  1. 2017年2月28日-----------乱码新手自学.net 之特性与验证
  2. 第二十章 排查和调试Web程序 之 设计异常处理策略
  3. zTree的重点
  4. Guice入门
  5. 纪念Google Reader&mdash;Google Reader的最后一天
  6. Elasticsearch-基本操作1
  7. telegraf1.8+influxdb1.6+grafana5.2 环境搭建 结合JMeter3.2
  8. nodeis 避免回调引起的栈溢出 Maximum call stack size exceeded
  9. JAVA多线程编程——JAVA内存模型
  10. stixel 理解