c与c++相互调用机制分析与实现
2015-12-12 10:10
399 查看
c++通常被称为Better c,多数是因为c++程序可以很简单的调用c函数,语法上基本实现兼容。最常用的调用方式就是c++模块调用c实现的dll导出函数,很简单的用法,使用
本文主要涉及到在c模块中如何调用c++函数,或者换个名字,
c++中的
通常,我们在需要调用c函数或者c实现的模块时,需要使用
c语言中的
近期在看JNI的调用实现机制,不自觉的在想c能调用c++模块吗?
基本的思路是来在于c++语言提供的
在c中按照下面方式调用
在c++实现如下函数:
在c中按照下面方式调用
在c中按照下面方式调用
其中四个文件,1-c-invoke-cpp.cpp(h)是c++中的实现文件(头文件),1-c-invoke-cpp-main.c(h)是c中的实现文件(头文件),其中包含主函数的测试代码。
编译和运行命令可以参考如下:
g++ -c 1-c-invoke-cpp.cpp
gcc -c 1-c-invoke-cpp-main.c
gcc 1-c-invoke-cpp.o 1-c-invoke-cpp-main.o -o invoke.exe
invoke
pause
针对c++实现中的
nm 1-c-invoke-cpp.o
...
00000000000000ac T _Z12OverloadFuncdb
0000000000000041 T _Z12OverloadFuncib
0000000000000000 T _Z6printfPKcz
0000000000000000 T _Z8DenyFuncv
0000000000000168 T _ZN5AType7MemFuncEi
0000000000000150 T _ZN5ATypeC1Ev
0000000000000150 T _ZN5ATypeC2Ev
000000000000015c T _ZN5ATypeD1Ev
000000000000015c T _ZN5ATypeD2Ev
00000000000001e4 T ClassMemFunc
000000000000018f T CreateInstance
00000000000001a7 T DestoryInstance
U free
000000000000001b T FunCppDecorate
U malloc
000000000000012c T OverloadDecorate_d
000000000000008d T OverloadDecorate_i
从上面输出可以明显看出c++和c的函数编译之后的修饰规则是不同的。
extern "C"将c头文件或者函数修饰下。
本文主要涉及到在c模块中如何调用c++函数,或者换个名字,
extern "C"在c语言中的功能介绍
c++中的extern "C"
通常,我们在需要调用c函数或者c实现的模块时,需要使用extern "C"修饰下对应的部分代码,告诉c++编译器按照c的调用规约调用相关模块代码。常见的形式如下:
extern "C" { // ffmpeg public header #include "avutil.h" #incluee "avcodec.h" // 函数声明,以c语言调用 int Func(int param); }
c语言中的extern "C"
近期在看JNI的调用实现机制,不自觉的在想c能调用c++模块吗?基本的思路是来在于c++语言提供的
extern "C"机制,既然可以在c++中写c模块,ok,那只需要一个中间层就可以让c调用c++的模块。
普通函数调用
在c++实现如下函数:// in header file(.h) extern "C" int FunCppDecorate(int param); // in implenmentation file(.cpp) int FunCppDecorate(int param) { printf("decorating by extern c, you have rights to invoke cpp function in c\nwith input %d\n" , param); return (param + 1); }
在c中按照下面方式调用
// declaration int FunCppDecorate(int param); // invoke FunCppDecorate(1);
重载函数调用
由于c不支持重载函数,如果需要c调用c++重载函数需要显式的给出调用的方式,并在c声明时给出对应对应机制。在c++实现如下函数:
// in header file(.h) void OverloadFunc(int param, bool is_c=false); void OverloadFunc(double param, bool is_c=false); extern "C" { void OverloadDecorate_i(int param); void OverloadDecorate_d(double param); } // in implenmentation file(.cpp) // ... void OverloadDecorate_i(int param) { OverloadFunc(param, true); } void OverloadDecorate_d(double param) { OverloadFunc(param, true); }
在c中按照下面方式调用
// declaration void OverloadDecorate_i(int param); void OverloadDecorate_d(double param); // invoke OverloadDecorate_i(1); OverloadDecorate_d(2.0);
类成员函数的调用
由于c++中类具有特殊的编译器附加的构造和析构函数,为了在c中可以访问c++的类,需要做一些c++编译器实现的功能,比如对象的构造和析构。c不能直接使用class名称,需要使用struct作为中转。实现调用如下:// in header file(.h) class AType { public: AType(); ~AType(); void MemFunc(int value); }; extern "C" { struct TagAType * CreateInstance(); void DestoryInstance(struct TagAType ** atype); void ClassMemFunc(struct TagAType * pthis, int param); } // in implenmentation file(.cpp) // ... extern "C" struct TagAType { AType a; }; struct TagAType * CreateInstance() { return (TagAType*)malloc(sizeof(TagAType)); } void DestoryInstance(struct TagAType ** atype) { if (NULL != atype && NULL != *atype) { free(*atype); atype = NULL; } } void ClassMemFunc(struct TagAType * pthis, int param) { if(NULL != pthis)pthis->a.MemFunc(param); }
在c中按照下面方式调用
// declaration struct TagAType; struct TagAType * CreateInstance(); void DestoryInstance(struct TagAType ** atype); void ClassMemFunc(struct TagAType * pthis, int param); // invoke struct TagAType * obj = CreateInstance(); ClassMemFunc(obj, 12); DestoryInstance(&obj);
小结
相关代码可以从我的git下载:https://git.oschina.net/Tocy/SampleCode.git ,位于c_c++目录下,名字前缀为1-c-invoke-cpp*。其中四个文件,1-c-invoke-cpp.cpp(h)是c++中的实现文件(头文件),1-c-invoke-cpp-main.c(h)是c中的实现文件(头文件),其中包含主函数的测试代码。
编译和运行命令可以参考如下:
g++ -c 1-c-invoke-cpp.cpp
gcc -c 1-c-invoke-cpp-main.c
gcc 1-c-invoke-cpp.o 1-c-invoke-cpp-main.o -o invoke.exe
invoke
pause
针对c++实现中的
extern "C"修饰符的作用,可以使用nm命令查看.o文件的输出格式,这是我使用gcc编译后的输出
nm 1-c-invoke-cpp.o
...
00000000000000ac T _Z12OverloadFuncdb
0000000000000041 T _Z12OverloadFuncib
0000000000000000 T _Z6printfPKcz
0000000000000000 T _Z8DenyFuncv
0000000000000168 T _ZN5AType7MemFuncEi
0000000000000150 T _ZN5ATypeC1Ev
0000000000000150 T _ZN5ATypeC2Ev
000000000000015c T _ZN5ATypeD1Ev
000000000000015c T _ZN5ATypeD2Ev
00000000000001e4 T ClassMemFunc
000000000000018f T CreateInstance
00000000000001a7 T DestoryInstance
U free
000000000000001b T FunCppDecorate
U malloc
000000000000012c T OverloadDecorate_d
000000000000008d T OverloadDecorate_i
从上面输出可以明显看出c++和c的函数编译之后的修饰规则是不同的。
相关文章推荐
- C++ Primer Plus第六版 第十七章 编程练习答案(完结篇...木有18章)
- C++ 模板详解(二)
- C51单片机学习(二):中断系统和定时器
- C++ Primer Pluse(第6版)中文版 第12章编程练习第5题
- C++ DLL 创建实例 导出类和函数
- C语言解释器Java版-3-内存值管理
- C++ 模板详解(一)
- ue4中的AI和行为树(c++版)
- 【源码分享】-c++界面源代码分享
- 实战c++中的string系列--string的遍历(使用下标还是iterator)
- 实战c++中的string系列--string的遍历(使用下标还是iterator)
- c++ float精度丢失
- Effective C++ :模板类之间的继承.
- 函数指针
- [C/C++]_[初级]_[关于static修饰符的说明]
- [C/C++]_[初级]_[关于static修饰符的说明]
- C++ Operators
- VC++ 简单的打印功能(对话框模式下)
- VC++ 实现文件与应用程序关联
- 操作系统: 银行家算法的分析和代码实现(c++语言)