c与c++相互调用机制分析与实现
c++通常被称为Better c,多数是因为c++程序可以很简单的调用c函数,语法上基本实现兼容。最常用的调用方式就是c++模块调用c实现的dll导出函数,很简单的用法,使用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与c++相互调用机制分析与实现的更多相关文章
- Android群英传》读书笔记 (4) 第八章 Activity和Activity调用栈分析 + 第九章 系统信息与安全机制 + 第十章 性能优化
第八章 Activity和Activity调用栈分析 1.Activity生命周期理解生命周期就是两张图:第一张图是回字型的生命周期图第二张图是金字塔型的生命周期图 注意点(1)从stopped状态重 ...
- Android消息机制之实现两个不同线程之间相互传递数据相互调用
目的:实现两个不同线程之间相互传递数据相互调用方法. 线程一中定义mainHandler 并定义一个方法mainDecode 线程二中定义twoHandler 并定义一个方法twoEncode 实现当 ...
- C语言栈调用机制初探
学习linux离不开c语言,也离不开汇编,二者之间的相互调用在源代码中几乎随处可见.所以必须清楚地理解c语言背后的汇编结果才能更好地读懂linux中相关的代码.否则会有很多疑惑,比如在head.s中会 ...
- Hybrid App开发模式中, IOS/Android 和 JavaScript相互调用方式
IOS:Objective-C 和 JavaScript 的相互调用 iOS7以前,iOS SDK 并没有原生提供 js 调用 native 代码的 API.但是 UIWebView 的一个 dele ...
- Python实例浅谈之三Python与C/C++相互调用
一.问题 Python模块和C/C++的动态库间相互调用在实际的应用中会有所涉及,在此作一总结. 二.Python调用C/C++ 1.Python调用C动态链接库 Python调用C库比较简单,不经过 ...
- Linux 线程实现机制分析 Linux 线程模型的比较:LinuxThreads 和 NPTL
Linux 线程实现机制分析 Linux 线程实现机制分析 Linux 线程模型的比较:LinuxThreads 和 NPTL http://www.ibm.com/developerworks/c ...
- C&C++——C函数与C++函数相互调用问题
C C++相互调用 在项目中融合C和C++有时是不可避免的,在调用对方的功能函数的时候,或许会出现这样那样的问题,但只要我的C代码和我的C++代码分别都能成功编译,那其他就不是问题.近来在主程序是C语 ...
- Python与C/C++相互调用(python2 调c++那个试了ok)
一.问题 Python模块和C/C++的动态库间相互调用在实际的应用中会有所涉及,在此作一总结. 二.Python调用C/C++ 1.Python调用C动态链接库 Python调用C库比较简单,不经过 ...
- Python与C/C++相互调用(转)
原文链接 作者 一.问题 Python模块和C/C++的动态库间相互调用在实际的应用中会有所涉及,在此作一总结. 二.Python调用C/C++ 1.Python调用C动态链接库 Python调用C库 ...
随机推荐
- 整理打印PI值
准备锻炼背诵PI的小数,找到PI值: PI=3. 141592653589793238462643383279502884197169399375105820974944592307816406286 ...
- I/O事件处理模型之Reactor和Proactor 【转】
http://blog.ddup.us/?p=280 这篇博客说的很清楚,赞一个: 在编写服务端软件的时候,如何处理各种I/O事件是其中很重要的一部分.在Unix Network Programmin ...
- vim自动缩进设置
需要软件 vim 下载地址 http://www.vim.org code_complete.vim 插件 http://www.vim.org/scripts/script.php?script ...
- 让Label等控件支持HTML格式的代码? 使用NSAttributedString:
> 如何让Label等控件支持HTML格式的代码? 使用NSAttributedString: NSString *htmlString = @"<div>Tate< ...
- C++转型操作符
转:http://www.cnblogs.com/hazir/archive/2012/04/14/2447251.html 旧式的C转型方式,几乎允许你将任何类型转换为任何其它类型,有其自身的缺陷, ...
- Mac添加快捷键开启应用程序(转)
最近使用终端比较多点,打开终端的方法有几种:比较常用有把终端添加到Dock栏上,然后就是利用Spotlight搜索Terminal来打开.但是两种方式还是让我感觉不太满意. 当开启的程序比较多的时候, ...
- linux\mac 日常入门命令行使用——搜索文件\文件夹
搜索文件或者文件夹,是一个常见的需求.我们可以用多种命令来实现我们的需求. find 命令实现搜索 find 是英文,寻找的意思.这个命令可以很方面的来搜索我们需要的内容. 标准命令如下: find ...
- “C++的数组不支持多态”?
先是在微博上看到了个微博和云风的评论,然后我回了“楼主对C的内存管理不了解”. 后来引发了很多人的讨论,大量的人又借机来黑C++,比如: //@Baidu-ThursdayWang:这不就c++弱爆了 ...
- ADS错误the session file 'C:\user\username\default-1-2-0-0.ses' could not be loaded解决办法
问题描述:用ADS1.2 + H-JTAG或者是H-Jlink,每次调试的时候都会出现“the session file could not be loaded”这个错误,寻求解决办法?问题解答:用户 ...
- tomcat jvm 参数优化
1. 内存设置 常见配置汇总 堆设置 -Xms:初始堆大小 -Xmx:最大堆大小 -XX:NewSize=n:设置年轻代大小 -XX:NewRatio=n:设置年轻代和年老代的比值.如:为3,表示年轻 ...