首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++与Objective-C混编

C++与Objective-C混编

作者头像
Helloted
发布于 2022-06-08 02:23:11
发布于 2022-06-08 02:23:11
1.8K00
代码可运行
举报
文章被收录于专栏: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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
域名和SSL证书监测管理平台部署过程
安装docker和docker-compose centos8安装docker和docker-compose
IT不难
2024/09/07
5860
域名和SSL证书监测管理平台部署过程
Domain Admin—基于Python + Vue3.js 技术栈实现的域名和SSL证书监测平台
话不多说,开始安装。Domain Admin支持pip安装,docker安装,源码安装,还有之前介绍过的1panel面板安装,在这篇文章里吗,我们依然采用的是docker的方式来安装
huolong
2023/10/25
6080
Domain Admin—基于Python + Vue3.js 技术栈实现的域名和SSL证书监测平台
【docker】域名SSL证书监测平台 | domain-admin
Domain Admin是一个轻量级监控方案,占用系统资源较少。能够帮助你管理不同网站的SSL证书,在证书即将过期的时候进行提醒,对于Let’s Encrypt证书还可以自动续期。可以很好的解决SSL证书过期导致网站无法正常访问的问题了~
夜梦星尘
2024/08/20
4060
【docker】域名SSL证书监测平台 | domain-admin
推荐一个非常轻便的ssl监控工具
如果大家有需要帮忙推荐的工具、框架、应用、脚本可以在文章下方留言,留言中被点赞、推荐回复较多的,波哥就会帮各位提前安排哦!
IT运维技术圈
2024/11/23
2140
推荐一个非常轻便的ssl监控工具
Ubuntu18.04搭建vue+django项目
公司要求按照生产环境进行部署,不能使用runserver方式启动django,查了一圈一般都是uwsgi,但是我弄不成功,有个同事之前公司使用了gunicorn+supervisor,试了试成功了。整理步骤记录下来。
用户10782352
2023/10/10
5630
python Web开发01
注意下python 项目的虚拟环境下。 使用pip install gunicorn 安装 gunicorn
Echo_Wish
2023/11/30
2600
如何在Debian 8上使用Postgres,Nginx和Gunicorn设置Django
Django是一个功能强大的Web框架,可以帮助您完成Python应用程序或网站。Django包含一个简化的开发服务器,用于在本地测试您的代码,但是对于任何与生产相关的细节,都需要一个更安全,更强大的Web服务器。
SQL GM
2018/08/10
4.3K0
Python3+uWSGI+Nginx部署Flask
第一次在服务器上面部署Flask应用程序,踩了挺多坑,还好最终成功部署,记录一下。
Naraku
2021/07/29
1.6K0
如何轻松做数据治理?开源技术栈告诉你答案
搭建一套数据治理体系耗时耗力,但或许我们没有必要从头开始搞自己的数据血缘项目。本文分享如何用开源、现代的 DataOps、ETL、Dashboard、元数据、数据血缘管理系统构建大数据治理基础设施。
NebulaGraph
2022/12/27
3.4K0
如何轻松做数据治理?开源技术栈告诉你答案
剖析Web技术栈(三)
正如我多次讨论过的,Web框架的作用是将HTTP请求转换为函数调用,将函数返回值转换为HTTP响应。框架的真正本质是一个层,它通过HTTP和相关协议将工作的业务逻辑连接到Web。该框架负责我们的会话管理,并将URL映射到函数,使我们能够专注于应用逻辑。
老齐
2020/05/14
1K0
剖析Web技术栈(四)
我们给Web server的一般标签是:用于执行任务的软件,nginx和Apache是两个常用的web server,这两个开源项目目前在市场上处于领先地位,它们使用不同的技术方法,都实现了我们在上一节中讨论的所有特性(以及更多特性)。
老齐
2020/05/15
8300
剖析Web技术栈(四)
腾讯云双十一活动:腾讯云轻量应用服务器快速搭建Python开发环境指南
双十一不仅仅是购物狂欢节,对于希望享受高性能云服务的企业和开发者而言,更是入手腾讯云产品的绝佳时机!然而,面对琳琅满目的产品与各种优惠活动,如何才能买到性价比最高的产品?本文将为你深入剖析腾讯云双十一的优惠机制,教你如何用最少的预算获取最佳的云服务配置,助你在年末冲刺中脱颖而出。
一键难忘
2024/11/10
9911
腾讯云双十一活动:腾讯云轻量应用服务器快速搭建Python开发环境指南
如何在Ubuntu 18.04上使用Gunicorn和Nginx为Flask应用程序提供服务
在本指南中,您将使用Ubuntu 18.04上的Flask微框架构建Python应用程序。本文的大部分内容将涉及如何设置Gunicorn应用程序服务器以及如何启动应用程序并将Nginx配置为充当前端反向代理。
物花无语
2018/10/19
3.6K0
Centos7 安装python虚拟环境+Django
鉴于virtualenv不便于对虚拟环境集中管理,所以推荐直接使用virtualenvwrapper。 virtualenvwrapper提供了一系列命令使得和虚拟环境工作变得便利。它把你所有的虚拟环境都放在一个地方。
py3study
2018/08/03
1.7K0
如何在Ubuntu 18.04上使用Postgres,Nginx和Gunicorn设置Django
Django是一个功能强大的Web框架,可以帮助您实现Python应用程序或网站。Django包含一个简化的开发服务器,用于在本地测试您的代码,但是对于任何与生产相关的细节,都需要一个更安全,更强大的Web服务器。
乌鸦
2018/10/25
7.2K0
Centos安装python3并使用Nginx+Gunicorn+virtualenv+supervisor来部署django项目
安装必要工具 yum-utils ,它的功能是管理repository及扩展包的工具 (主要是针对repository)
緣來
2018/09/18
2.2K0
Centos安装python3并使用Nginx+Gunicorn+virtualenv+supervisor来部署django项目
VolWeb:集中式增强型数字取证内存分析平台
VolWeb是一款最新开发的集中式增强型数字取证内存分析平台,该平台基于Volatility 3框架实现其功能,该工具旨在辅助广大研究人员执行安全分析和事件应急响应等任务。
FB客服
2024/05/27
1870
VolWeb:集中式增强型数字取证内存分析平台
如何在Ubuntu 18.04上安装Django Web Framework
Django是一个功能齐全的Python Web框架,用于开发动态网站和应用程序。使用Django,您可以快速创建Python Web应用程序,并依靠该框架来完成繁重的工作。
苏子晨
2018/10/11
3K0
如何在树莓派上安装MyEMS开源能源管理系统(上)
默认情况下,MySQL安装时没有设置任何密码,这意味着您无需任何身份验证即可访问MySQL服务器。运行以下命令以开始MySQL保护过程。
开源能源管理系统
2025/05/13
970
Jumpserver0.4.0基于Cen
因为centos6/7自带的python环境都是2,而yum等工具依赖原来的Python,为了不扰乱原来的环境我们使用Python虚拟环境
py3study
2020/01/08
4350
推荐阅读
相关推荐
域名和SSL证书监测管理平台部署过程
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验