参考文章:
http://blog.csdn.net/caspiansea/article/details/9676153
https://www.cnblogs.com/eyeszjwang/articles/2839175.html
在c++文件中声明一个非C++函数中的extern “C”的作用(C++调用c函数)是让C++链接器在找调用函数的符号时采用c的方式
导出C++函数到其他语言中(c语言调用c++)extern “C”的作用是告诉编译器依照C的方式来编译封装接口,但接口函数里面的C++语法还是按C++方式编译
一、C++中调用C的代码,具体方式有以下几种:
1.moduleA.h:
#ifndef MODULE_A_H
#define MODULE_A_H
int foo(int i);
#endif
moduleA.c:
#include<stdio.h>
#include"moduleA.h"
int foo(int i)
{
printf("I love you !");
return 0;
}
moduleB.cpp:
#include<stdio.h>
extern "C" {
#include"moduleA.h"
}
int main()
{
foo(1);
return 0;
}
makefile:
xrb:moduleA.o moduleB.o
g++ -o xrb.exe moduleA.o moduleB.o
@echo "makefile"
moduleA.o:moduleA.c
gcc -c moduleA.c
moduleB.o:moduleB.cpp
g++ -c moduleB.cpp
.PHONY: clean
clean:
rm xrb.exe moduleA.o moduleB.o
@echo "makefile"
运行结果:
2.extern “C”可以用在.cpp文件中,也可以用在.c文件中,也能用在c语言头文件(.h文件)中,用在.c和c语言头文件中会不会报错,关键是使用gcc还是g++编译,gcc编译会报错,g++编译不会报错:
(1)extern “C”在c语言头文件中,用gcc编译报错,用g++编译可以通过
moduleA.h:
#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo();
#endif
moduleA.c:
#include<stdio.h>
#include"moduleA.h"
int foo(void)
{
printf("I love you !");
return 0;
}
moduleB.cpp:
#include<stdio.h>
#include"moduleA.h"
int main()
{
foo();
return 0;
}
makefile:
xrb:moduleA.o moduleB.o
g++ -o xrb.exe moduleA.o moduleB.o
@echo "makefile"
moduleA.o:moduleA.c
gcc -c moduleA.c
moduleB.o:moduleB.cpp
g++ -c moduleB.cpp
.PHONY: clean
clean:
rm xrb.exe moduleA.o moduleB.o
@echo "makefile"
运行结果:
(2)extern “C”在.c中,用g++编译不会报错,成功:
module.c:
#include<stdio.h>
//#include"moduleA.h"
extern "C" int main(void)
{
printf("I love you !");
return 0;
}
执行g++ module.c即可
3.网上说的第三种方法也是错的。
/*C语言头文件:CDemo.h */
#ifndef C_SRC_DEMO_H
#define C_SRC_DEMO_H
extern int Function(int x,int y);
#endif // C_SRC_DEMO_H
/* C语言实现文件:CDemo.c */
#include "CDemo.h"
int Function ( int x, int y )
{
... // processing code
}
// C++调用文件
#include "CDemo.h"
extern "C" int Function(int x,int y);
int main()
{
Function (2,3);
return 0;
}
二、C中调用C++代码
1.代码:
moduleA.h:
#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo(int i);
#endif
module.cpp:
#include<iostream>
#include"moduleA.h"
using std::cout;
using std::endl;
int foo(int i)
{
cout<<"I love you !"<<endl;
return 0;
}
moduleB.c:
#include<stdio.h>
extern int foo(int i);
int main()
{
foo(1);
return 0;
}
makefile:
xrb:module.o moduleB.o
g++ -o xrb.exe module.o moduleB.o
@echo "makefile"
module.o:module.cpp
g++ -c module.cpp
moduleB.o:moduleB.c
gcc -c moduleB.c
.PHONY: clean
clean:
rm xrb.exe module.o moduleB.o
@echo "makefile"
运行结果:
这个例子可见,导出C++函数到其他语言中(c语言调用c++)extern “C”的作用是告诉编译器依照C的方式来编译封装接口,但接口函数里面的C++语法还是按C++方式编译。
2.代码:
moduleA.h:
#ifndef MODULE_A_H
#define MODULE_A_H
#ifdef __cplusplus
extern "C" {
#endif
int foo(int i);
#ifdef __cplusplus
}
#endif
#endif
module.cpp:
#include<iostream>
#include"moduleA.h"
using std::cout;
using std::endl;
int foo(int i)
{
cout<<"I love you !"<<endl;
return 0;
}
moduleB.c:
#include<stdio.h>
#include"moduleA.h"
int main()
{
foo(1);
return 0;
}
makefile:
xrb:module.o moduleB.o
g++ -o xrb.exe module.o moduleB.o
@echo "makefile"
module.o:module.cpp
g++ -c module.cpp
moduleB.o:moduleB.c
gcc -c moduleB.c
.PHONY: clean
clean:
rm xrb.exe module.o moduleB.o
@echo "makefile"
运行结果:
3.用C语言调用C++的类
1.代码:
moduleA.h:
#ifndef MODULE_A_H
#define MODULE_A_H
class Apple
{
public:
Apple();
int send(void);
private:
int i;
};
#endif
module.cpp:
#include<iostream>
#include"moduleA.h"
using std::cout;
using std::endl;
Apple::Apple():i(10)
{
}
int Apple::send(void)
{
cout<<"I love you !"<<" "<<i<<endl;
return 0;
}
moduleB.h:
#ifndef MODULE_B_H
#define MODULE_B_H
struct tagApple;
#ifdef __cplusplus
extern "C" {
#endif
struct tagApple *GetInstance(void);
int tagsend(struct tagApple *pApple);
#ifdef __cplusplus
}
#endif
#endif
这里使用了#ifdef __cplusplus,这样在test.c包含moduleB.h并用gcc编译test.c的时候不会因为extern “C”报错
moduleB.cpp:
#include"moduleB.h"
#include"moduleA.h"
struct tagApple{
Apple apple;
};
struct tagApple *GetInstance(void)
{
return new struct tagApple;
}
int tagsend(struct tagApple *pApple)
{
return pApple->apple.send();
}
test.c:
#include "moduleB.h"
#include<stdio.h>
extern struct tagApple *GetInstance(void);
extern int tagsend(struct tagApple *pApple);
int main(void)
{
struct tagApple *pApple;
pApple=GetInstance();
tagsend(pApple);
printf("Yes~");
return 0;
}
makefile:
#下面这个编译不知道为什么一定要把-lmodule加上,我觉得只加上-lmoduleB就够了(其实我也不懂。。)。
#2018.1.10补充:参看http://blog.csdn.net/cjsycyl/article/details/46864341这篇文章可以更新下面的#makefile#以及解释为什么要加上-lmoduleB
xrb:libmoduleB.so test.c
gcc test.c -L. -lmoduleB -lmodule -o xrb.exe
@echo "makefile"
libmoduleB.so:moduleB.cpp libmodule.so
g++ -o libmoduleB.so -fpic -shared moduleB.cpp -L. -lmodule
libmodule.so:module.cpp
g++ -o libmodule.so -fpic -shared module.cpp
.PHONY: clean
clean:
rm xrb.exe libmodule.so libmoduleB.so
@echo "makefile"
这样就可以编译成功了,不过在运行前,要在命令行输入
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
上面的makefile在ubuntu中可以运行成功,在windows会报错