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)

上一篇 下一篇

猜你喜欢

热点阅读