本文转载自微信公众号《编程学习基地》,作者deroy。转载本文请联系编程学习基地公众号。前言如何在C++代码中调用写好的C接口?您可能想知道,C++不是与C兼容吗?直接调用是不行的,我们来测试一下,看看C++是如何调用C代码接口的。C++把一个C文件称为C语言文件test.c#includevoidprint(inta,intb){printf("ThisisaClanguagefunction:%d,%d\n",a,b);}头文件test.h#ifndef_TEST_H#define_TEST_Hvoidprint(inta,intb);#endifC++文件调用C函数#includeusingnamespacestd;#include"test.h"intmain(){cout<<"现在调用C语言Function\n";print(3,4);return0;}执行命令gcc-ctest.cg++-omainmain.cpptest.o链接错误:undefinedreferencetoprint(int,int)inmain.cpp。那么为什么g++编译器找不到print(int,int)呢?其实我们在学习C++重载的时候就提到了C++的底层编译原理。原因分析test.c是使用C语言编译器gcc编译的。函数print编译后,在符号表中的名称为print,可以通过nm查看.o文件。$gcc-ctest.c$nmtest.oU_GLOBAL_OFFSET_TABLE_0000000000000000TprintUprintf我们链接的时候是用g++链接的,也就是C++的链接方式。当程序运行到调用print函数的代码时,会在符号表中查找_Z5printii(根据C++的链接方式查找,所以查找的是_Z5printii,而不是print的名称),但是不能$g++-ctest.c$lsmain.cppmakefiletest.ctest.htest.o$nmtest.oU_GLOBAL_OFFSET_TABLE_Uprintf0000000000000000T_Z5printii如果我们在打印的语句中加上extern"C",就会提示"undefinedreference"这时g++编译器会按照C语言的链接方式进行查找,即在符号表中查找print(这是C++兼容C)。这时候,有可能找到了,就不会报错了。综上所述,编译后底层解析出来的symbol是不一样的。C语言是_print,C++是__Z5printii,解决调用失败问题。修改test.h文件#ifndef_TEST_H#define_TEST_Hextern"C"{voidprint(inta,intb);}#endif修改后再次执行命令gcc-ctest.cg++-omainmain.cpptest.o./main运行没有报错。思考:C语言能否调用C接口实验:定义main.c函数如下#include#include"test.h"intmain(){printf("现在调用C语言函数\n");print(3,4);return0;}重新执行命令如下gcc-ctest.cgcc-omianmain.ctest.o报错:C语言中没有extern"C"这种写法,C接口可以被C++和C调用,为了让test.c代码可以被C++和C调用,修改test.h如下#ifndef__TEST_H__#define__TEST_H__#ifdef__cplusplus#if__cplusplusextern"C"{#endif#endif/*__cplusplus*/externvoidprint(inta,intb);#ifdef__cplusplus#if__cplusplus}#endif#endif/*__cplusplus*/#endif/*__TEST_H__*/ps:下期介绍一个快速生成的SourceInsight插件以上代码再次执行命令gcc-ctest.cgcc-omainmain.ctest.o./main,结果显示: