Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++与Objective-C混编

C++与Objective-C混编

作者头像
Helloted
发布于 2022-06-08 02:23:11
发布于 2022-06-08 02:23:11
1.7K00
代码可运行
举报
文章被收录于专栏:HellotedHelloted
运行总次数:0
代码可运行

在一些iOS开发中,经常有一些第三方的框架是用C++写的,有时候我们需要在C++文件中调用OC方法,或者在OC文件中调用C++函数,也就是C++与Objective-C混编。但是我们知道在纯OC文件中是不能编译C++代码的,在纯C++文件中又是不能编译Objective-C代码的。直接引入编译不过会报错

如果要同时混编,就要利用下面的几种方式。

  • Objective-C++
  • C函数桥接
  • 运行时
一、通过Objective-C++

Objective-C++是C++的超集,就如同Objective-C是C的超集,在OS X上同时被GCC和Clang支持编译,能够不用C++来初始化OC对象和调用方法。只要在C ++模块的实现中隐藏Objective-C header导入和类型,它就不会感染任何“纯”C ++代码。

.mm是Objective-C++的默认后缀名,Xcode会自动识别。在.mm文件中,Objective-C代码和C++代码都可以正常编译运行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//MyClass.h
class MyClass
{
  public:
    double secondsSince1970();
};


//MyClass.mm
#include "MyClass.h"
#import <Foundation/Foundation.h>

double MyClass::secondsSince1970()
{
  return [[NSDate date] timeIntervalSince1970];
}


//Client.cpp
...
MyClass c;
double seconds = c.secondsSince1970();

二、通过C函数来桥接

我们知道Objective-C和C++都是在C语言的基础上发展而来的语言,都能同时支持C函数,所以我们可以通过C函数来桥接,从而能够编译。

先定义一个.h文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//CppOCBridge.h
typedef void (*interface) (void* caller,void* parameter);

自定义一个OC类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//  TargetOC.h

#import <Foundation/Foundation.h>
#import "CppOCBridge.h"

@interface TargetOC : NSObject

- (void)doFirstMethodWith:(void*)parameter;
- (void)doSecondMethodWith:(void *)parameter;

@property interface doFirstMethod;
@property interface doSecondMethod;

@end
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//  TargetOC.m

#import "TargetOC.h"

void OcObjectDoFirstMethodWithWith(void *ocInstance, void *parameter){
    [(__bridge id)ocInstance doFirstMethodWith:parameter];
}

void OcObjectDoSecondMethodWithWith(void *ocInstance, void *parameter){
    [(__bridge id)ocInstance doSecondMethodWith:parameter];
}

@implementation TargetOC

-(instancetype)init{
    if ([super init]) {
        _doFirstMethod = OcObjectDoFirstMethodWithWith;
    }
    return self;
}

-(void)doFirstMethodWith:(void *)parameter{
    NSLog(@"oc doFirstMethodWith parameter==== %@",parameter);
}

- (void)doSecondMethodWith:(void *)parameter{
    NSLog(@"oc doSecondMethodWith parameter==== %@",parameter);
}

@end

那么,在一个C++类里,如果我们要调用一个方法的话,我们定义一个类ObjectCpp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void ObjectCpp::call_oc_function(void *ocObj, interface function, void *parameter){
    function(ocObj,parameter);
}

调用OC方法的步骤为

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    TargetOC *ocObj = [[TargetOC alloc]init];
    ObjectCpp *cpp = new ObjectCpp; 
    cpp->call_oc_function((__bridge void*)ocObj,ocObj.doFirstMethod,(__bridge void*)@"this is paras");

OC对象和方法都被包装成一个参数来进行调用,从而达到混编的目的

三、运行时objc_msgSend

一提到将OC方法变成C函数,肯定会想到运行时,在Objective-C中,消息在运行时才被绑定到方法实现。

编译器会将一个下面的一个消息表达式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[receiver message]

转变成一个消息函数 objc_msgSend,这个函数将接收者和消息中提到的方法的名称(即方法selector)作为其两个主要参数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
objc_msgSend(receiver, selector)

消息中传递的其他参数也在 objc_msgSend被处理

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
objc_msgSend(receiver, selector, arg1, arg2, ...)

所以,利用objc_msgSend也可以达到混编的目的

假设我们有一个OC对象NewObject继承自NSObject:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@interface NewObject : NSObject

- (void)doSomethingWith:(char *)paras;

@end

正常在OC环境中,如果我们需要调用方法的话,步骤是这样的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
NewObject *myobj = [[NewObject alloc]init];
[myobj doSomethingWith:@"abc"];

在运行时编译时,将被转换成:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    void *myobj = objc_msgSend((id)objc_getClass("NewObject"), sel_registerName("alloc"), sel_registerName("init"));
    objc_msgSend((id)myobj, sel_registerName("doSomethingWith:"), (char *)"abc");

如果是类方法则更简单了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
objc_msgSend((id)objc_getClass("NewObject"), sel_registerName("doThirdMethod:"), 1);

可以很清楚地看到,通过objc_getClas获取到了类,通过sel_registerName获得方法,而上面两个方法都是C函数方法,可以在C++文件中顺利调用,不过要注意先引入头文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#import <objc/runtime.h>
#import <objc/message.h>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
iOS runtime探究(二): 从runtime开始深入理解OC消息转发机制你要知道的runtime都在这里
你要知道的runtime都在这里 转载请注明出处 https://cloud.tencent.com/developer/user/1605429 本文主要讲解runtime相关知识,从原理到实践,由于包含内容过多分为以下五篇文章详细讲解,可自行选择需要了解的方向: 从runtime开始: 理解面向对象的类到面向过程的结构体 从runtime开始: 深入理解OC消息转发机制 从runtime开始: 理解OC的属性property 从runtime开始: 实践Category添加属性与黑魔法method sw
WWWWDotPNG
2018/04/10
9690
iOS runtime探究(二): 从runtime开始深入理解OC消息转发机制你要知道的runtime都在这里
Objective-C Runtime 的一些基本使用
在上一篇文章《Objective-C Runtime详解》中我们探讨了Runtime的基本原理,这篇文章我们将总结一下Runtime的一些基本使用 目录 查询方法 给分类添加属性 更换代码的实现方法 动态添加方法 字典转属性 先创建两个类 ClassA.h #import <Foundation/Foundation.h> @interface ClassA : NSObject { // 公有变量 NSString *_publicVar1; NSString *_publ
BY
2018/05/11
1.2K0
[super class]和[self class]
按照我们的常规理解,super对应的应该打印Parent啊,为啥最后打印的是Son呢?
拉维
2019/11/21
6750
[super class]和[self class]
【IOS开发高级系列】Objective-c Runtime专题总结
http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/
江中散人_Jun
2023/10/16
4070
【IOS开发高级系列】Objective-c Runtime专题总结
《Effective Objective-C》干货三部曲(一):概念篇
本书是iOS程序员入门的必读书籍,它讲述了在iOS开发中(Objective-C语言)可以遵循的规范和一些开发技巧。
用户2932962
2018/08/30
9630
《Effective Objective-C》干货三部曲(一):概念篇
iOS底层原理之Runimte 运行时&方法的本质
前面探究了类里面的重要的变量,iOS 底层原理之cache分析分析了缓存方法调用流程。
CC老师
2022/01/11
4150
iOS底层原理之Runimte 运行时&方法的本质
Objective-C Runtime编程指南(1)
苹果官方文档Objective-C Runtime Programming Guide
Helloted
2022/06/06
8430
Objective-C Runtime编程指南(1)
Objective-C关于id引发的一些思考 原
    Objective-C是面向对象语言,但其中又并非全部是对象。在初学这门语言时,我常常从意识上将NS开头的类型与C语言原本的那些类型分割开来,假装他们之间没有联系,只关注“类”的世界。然而类终究只是一种应用上的抽象,就像“语法糖”一样,抛开华丽的外表,内部依然是最朴素的结构体和指针。本篇博客的来由源自朋友的一个问题:在ARC环境,performSelector:withObject:方法如何传递非对象类型的数据呢?这个问题乍看起来简单,但要较较真,却也并非那么简单。下面的内容都是有这个简单的问题引出的,如果你感兴趣,在读之前可以先试着解决下上面的疑问。
珲少
2018/08/15
1.1K0
Objective-C关于id引发的一些思考
                                                                            原
objc_msgSend 实现分析
Runtime 有两个版本:Legacy 版本(早期版本,对应 Objective-C 1.0) 和 Modern 版本(现行版本 Objective-C 2.0)。
网罗开发
2021/07/21
9400
Objective-C笔记
为什么突然要搞ObjectiveC?因为清明比较闲,两三天正好用来学习下iOS的逆向分析。 逆向的第一步当然是先从正向了解,否则给你源代码都看不懂,反编译出来的就更别提了。 因此本篇文章作为简单学习ObjC的记录,不会涉及太深入的语法特性,简而言之就是——够用就行。
evilpan
2023/02/12
9990
Objective-C笔记
神经病院Objective-C Runtime住院第二天—消息发送与转发
现在越来越多的app都使用了JSPatch实现app热修复,而JSPatch 能做到通过 JS 调用和改写 OC 方法最根本的原因是 Objective-C 是动态语言,OC 上所有方法的调用/类的生成都通过 Objective-C Runtime 在运行时进行,我们可以通过类名/方法名反射得到相应的类和方法,也可以替换某个类的方法为新的实现,理论上你可以在运行时通过类名/方法名调用到任何 OC 方法,替换任何类的实现以及新增任意类。今天就来详细解析一下OC中runtime最为吸引人的地方。
一缕殇流化隐半边冰霜
2018/08/29
7940
神经病院Objective-C Runtime住院第二天—消息发送与转发
《Objective-C高级编程》温故知新之"自动引用计数"
1、使用alloc、new、copy、mutableCopy的意味着自己生成的对象只有自己持有
Dwyane
2018/08/03
6540
《Objective-C高级编程》温故知新之"自动引用计数"
MessageMock : 优雅的模拟 Objective-C 方法
我们在调试代码或编写单元测试时,为了触发特定场景,往往需要通过一系列前置操作,或者直接修改源代码数据。实际上更期望有一种不需侵入源码且更快捷的方式,知名的 OCMock 正是为了解决这些问题,不过它有不支持多线程、接口怪异、重复调用、类型处理复杂等问题,笔者看了源码过后决定换一种思路,基于objc_msgSend来进行方法的“模拟”和“校验”。
波儿菜
2020/08/04
8790
MessageMock : 优雅的模拟 Objective-C 方法
Objective-C Runtime 详解
Objective-C的方法调用实则为“发送消息”,我们来看[dog eat]实际会被编译器转化为
零式的天空
2022/03/28
1.3K0
Objective-C Runtime 详解
runtime的那些事(一)——runtime基础介绍
一、 什么是runtime? 二、 runtime 版本 三、 与 runtime 的三种交互方式 四、 消息机制的基本原理与执行流程 五、 动态解析与消息转发
我只不过是出来写写代码
2019/04/22
1.6K0
runtime的那些事(一)——runtime基础介绍
动态的Objective-C——关于消息机制与运行时的探讨
    Objective-C是一种很优美的语言,至少在我使用其进行编程的过程中,是很享受他那近乎自然语言的函数命名、灵活多样的方法调用方式以及配合IDE流顺畅快编写体验。Objective-C是扩展与C面向对象的编程语言,然而其方法的调用方式又和大多面向对象语言大有不同,其采用的是消息传递、转发的方式进行方法的调用。因此在Objective-C中对象的真正行为往往是在运行时确定而非在编译时确定,所以Objective-C又被称为是一种运行时的动态语言。
珲少
2018/08/15
8440
动态的Objective-C——关于消息机制与运行时的探讨
iOS @property探究(二): 深入理解你要知道的@property都在这里
你要知道的@property都在这里 转载请注明出处 https://cloud.tencent.com/developer/user/1605429 上一篇文章iOS @property探究(一):基础详解介绍了@property的基本原理和使用方法,以及相关修饰符详解。 本文将会深入底层探究@property的本质。 在进入正题之前,先介绍一个clang编译器的命令 clang -rewrite-objc main.m 这个命令用于clang重写.m文件为.cpp文件。 @property深入代
WWWWDotPNG
2018/04/10
1.1K0
「类与对象」揭秘本质的第一步
若想了解Objective-C一些API具体实现以及一些对象真实的数据结构等,就需要将Objective-C语言转化成C/C++语言。
Jacklin
2019/11/25
4400
A interesting inheritance question between self and super
Here is a inheritance chain relationship: NSObject -> RootCls -> SubCls Think About a question? What
Mitchell
2018/09/30
3890
Objective-C RunTime概览
一篇文章,不可能讲完Runtime的全部,但是,分成很多篇讲,又有点「见树木不见森林」的迷糊感觉——自己就是看了很多关于Runtime的文章,看完还是「迷雾重重」(当然,也可能因为资质太过平庸)。
iOS Development
2019/02/14
7050
推荐阅读
相关推荐
iOS runtime探究(二): 从runtime开始深入理解OC消息转发机制你要知道的runtime都在这里
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验