美文网首页
OC与C++交互案例(2)

OC与C++交互案例(2)

作者: 浅_若清风 | 来源:发表于2021-07-19 17:07 被阅读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)

    相关文章

      网友评论

          本文标题:OC与C++交互案例(2)

          本文链接:https://www.haomeiwen.com/subject/axlhmltx.html