OC与C++交互案例(2)
2021-07-19 本文已影响0人
浅_若清风
最近做的一个关于车型诊断的项目,因为IOS不支持动态库加载,所以C++编写的所有诊断代码都需要嵌入到IOS工程中,以下记录一下关于OC与C++交互的实现过程。
完整示例代码
1.定义一个过渡层中间类DiagExeFile,继承于NSObject,把DiagExeFile.m修改成DiagExeFile.mm。把交互的方法写到该类里面。
//DiagExeFile.h文件实现
@protocol DiagExeFileDelegate <NSObject>
//设置代理方法,接收上层传回来的JSON字串或byte数组字串
- (NSString *)interactWithTheData:(NSString *)JSONStr;
@end
@interface DiagExeFile : NSObject
//执行数据交互的代理
@property (nonatomic, weak) id<DiagExeFileDelegate> dataDelegate;
//单例函数
+ (DiagExeFile *)sharedExeFile;
//诊断功能的函数入口(我这里设置了三个参数)
- (void)begainDaignose:(NSString *)diagName typeInt:(int)type appDir:(NSString *)appDirStr;
@end
//DiagExeFile.mm文件实现
@interface DiagExeFile ()
{
dispatch_queue_t myQueue;
}
@end
@implementation DiagExeFile
//单例对象
static DiagExeFile *myExeFile;
//创建单例对象
+ (DiagExeFile *)sharedExeFile{
static dispatch_once_t token;
dispatch_once(&token, ^{
myExeFile = [[self alloc] init];
});
return myExeFile;
}
//重写初始化方法,进行一些变量的初始化
- (instancetype)init
{
self = [super init];
if (self) {
// 创建并发队列
myQueue = dispatch_queue_create("exeEntryFunc", DISPATCH_QUEUE_CONCURRENT);
}
return self;
}
#pragma mark -------------- 功能函数的实现 -------------------
- (void)begainDaignose:(NSString *)diagName typeInt:(int)type appDir:(NSString *)appDirStr{
if ([NSThread isMainThread])
{
//异步线程
dispatch_async(myQueue, ^{
CDiagnosisFrame *theApp = new CDiagnosisFrame(myCallBack);
theApp->InitInstance((char *)[diagName UTF8String],(int)type,(char *)[appDirStr UTF8String]);
});
}
else{
CDiagnosisFrame *theApp = new CDiagnosisFrame(myCallBack);
theApp->InitInstance((char *)[diagName UTF8String],(int)type,(char *)[appDirStr UTF8String]);
}
}
#pragma mark ------------- 处理回调数据 ------------------
char *myCallBack(const char* buff, int nLen, int *outLen)
{
//根据自身需要去处理你回调的数据(以下是我的项目的部分处理代码逻辑)
return [myExeFile sendData:buff andLen:nLen andOutLen:outLen];
}
//将C层回调的数据都传给该函数处理,方便进行OC风格的编码(根据自身需要处理数据类型)
- (char *)sendData:(const char*) buff andLen: (int)len andOutLen:(int *)outLen{
//将接收过来的C风格JSON字串转换成字典
NSString *JSONString = [NSString stringWithCString:buff encoding:NSUTF8StringEncoding];
//局部变量若需要在block中修改其值,需要在声明前加 __block
__block NSString *str = nil;
if (self.dataDelegate && [self.dataDelegate respondsToSelector:@selector(interactWithTheData:)]) {
//回调需要放于子线程回调到OC,防止主线程占用导致回调不及时
if ([NSThread isMainThread]) {
dispatch_async(myQueue, ^{
str = [self.dataDelegate interactWithTheData:JSONString];
});
}
else{
str = [self.dataDelegate interactWithTheData:JSONString];
}
}
//将从上层接收回来的OC类型字串转换成C风格字串返回到C层
NSUInteger length = [str length];
*outLen = (int)length;
char *myStr = (char *)malloc(length+1);
memset(myStr, 0, length+1);
char *tmpString = (char *)[str UTF8String];
//将字符串转化为16进制数
StrToHex((unsigned char *)myStr, tmpString, (unsigned int)length/2);
return myStr;
}
@end
2.在C++文件里实现InitInstance方法。首先在DiagnosisFrame.h或.hpp(我这里转成了.h文件)里声明InitInstance方法,在DiagnosisFrame.cpp文件里实现。
//DiagnosisFrame.h文件实现
class CDiagnosisFrame
{
public:
int InitInstance(char *diagApp,int type,char *appDir);
};
//DiagnosisFrame.cpp文件实现
int CDiagnosisFrame::InitInstance(char *diagApp,int type,char *appDir)
{
//在此编辑你的C++代码
return xxx;
}
3.在OC的.m文件里处理和C++的交互
//需要交互的OC的.m文件
DiagExeFile *diag = [DiagExeFile sharedExeFile];
[diag setDataDelegate:self];
//诊断功能的函数入口
//把参数1、2、3传给C++
[diag begainDaignose:"参数1" typeInt:"参数2" appDir:"参数3"];
#pragma mark DiagExeFileDelegate
-(NSString *)interactWithTheData:(NSString *)JSONStr
{
//在此处理C层回调的数据
}
该案例比较复杂,可参考OC和C++交互案例(1)