iOS OC 项目集成 C++ 算法库完整指南

iOS OC 项目集成 C++ 算法库完整指南


一、概述思路与实现方式

1.1 核心思路

在 iOS 原生 Objective-C 项目中集成 C++ 算法库,核心思路和 Android 的 JNI 类似,但实现方式更轻量 。我们不需要像 Android 那样通过 JNI 接口层和 javac/javah 工具生成头文件,而是直接利用 Xcode 对 Objective-C++ 的原生支持。

本质就是:给 C++ 代码套上一层 Objective-C 的"壳",让 OC 业务层完全感知不到 C++ 的存在。

术语:

"在 iOS 中,我们通过 Objective-C++ 编写一个 Wrapper 层,来封装 C++ 算法库,为上层提供 OC 接口。"

  • 最标准的说法是 "Objective-C++",这是 Apple 官方术语。
  • 最常用的开发语境是 "OC++ Wrapper",清晰明了。
  • "Bridge/桥接层" 是口语化的概念描述,不是标准术语,但大家能听懂。
  • 绝对不要叫 "iOS JNI",这是外行说法。

1.2 三层架构

复制代码
┌─────────────────────────────────────────┐
│  第 1 层:OC 业务层                     │
│  (ViewController.m)                     │
│  只写 OC 代码,不涉及任何 C++           │
└─────────────────┬───────────────────────┘
                  │ 调用 OC 接口
┌─────────────────▼───────────────────────┐
│  第 2 层:OC 桥接层 (关键)              │
│  (Bridge.mm)                            │
│  Objective-C++ 混编文件                  │
│  翻译:OC 方法 → C++ 方法调用           │
└─────────────────┬───────────────────────┘
                  │ 持有 C++ 对象
┌─────────────────▼───────────────────────┐
│  第 3 层:C++ 算法层                    │
│  (Algorithm.cpp)                        │
│  纯 C++ 实现,跨平台可复用              │
└─────────────────────────────────────────┘

1.3 关键技术点

技术点 说明
.mm 文件 Objective-C++ 源文件,同时支持 OC 和 C++ 语法
C++ 对象管理 C++ 对象需要手动 new/delete,ARC 不负责
类型转换 NSStringstd::stringNSIntegerint
头文件隔离 桥接类的 .h 不能包含任何 C++ 代码,避免污染纯 OC 文件

1.4 与 JNI 的对比

对比项 Android JNI iOS OC++
桥接语言 C/C++ Objective-C++
桥接文件 .c/.cpp + javah 生成头文件 .mm 直接编写
对象管理 JNI 局部/全局引用 C++ 手动 new/delete + ARC
类型映射 jstringchar* NSString*std::string
回调实现 JNI 回调 Java 方法 函数指针/std::function + dispatch_async

二、项目整体结构

2.1 目录结构

复制代码
MyApp/
├── MyApp.xcodeproj/
│
├── MyApp/                              # 主工程目录
│   │
│   ├── AppDelegate.h/m                 # OC - 应用代理
│   │
│   ├── ViewControllers/                # 📂 OC 业务层
│   │   ├── MainViewController.h
│   │   └── MainViewController.m
│   │
│   ├── Bridge/                         # 📂 🔑 桥接层(重点)
│   │   ├── CalculatorBridge.h          # OC 接口声明(纯 OC)
│   │   └── CalculatorBridge.mm         # OC++ 实现(混编)
│   │
│   ├── CPP/                            # 📂 C++ 算法核心
│   │   ├── Algorithms/
│   │   │   ├── Calculator.hpp          # C++ 类声明
│   │   │   └── Calculator.cpp          # C++ 类实现
│   │   └── ThirdParty/                 # 第三方 C++ 库
│   │       ├── include/
│   │       └── lib/
│   │
│   ├── Models/                         # 📂 OC 数据模型
│   ├── Resources/                      # 📂 资源文件
│   └── main.m                          # OC 程序入口
│
└── Tests/                              # 单元测试

2.2 文件类型速查表

文件后缀 存放位置 编译方式 职责
.h 各处 不单独编译 接口声明(OC 或 C++)
.m ViewControllers/, Models/ Objective-C UI、业务逻辑
.mm Bridge/ Objective-C++ OC ↔ C++ 翻译桥接
.hpp CPP/ 不单独编译 C++ 类/函数声明
.cpp CPP/ C++ 核心算法实现

2.3 依赖关系图

复制代码
MainViewController.m
       │ #import "CalculatorBridge.h"
       ▼
CalculatorBridge.h (纯 OC 接口)
       │
       ▼
CalculatorBridge.mm (OC++ 实现)
       │ #import "Calculator.hpp"
       │ 持有 C++ 对象指针
       ▼
Calculator.hpp + Calculator.cpp (纯 C++)

三、关键示例代码

3.1 C++ 算法层:累加器

Calculator.hpp(头文件 - 声明)

cpp 复制代码
#pragma once

class Calculator {
public:
    Calculator();           // 构造函数
    ~Calculator();          // 析构函数
    
    int add(int value);     // 累加并返回结果
    void reset();           // 重置为 0
    int getCurrent() const; // 获取当前值
    
private:
    int _sum;
};

Calculator.cpp(源文件 - 实现)

cpp 复制代码
#include "Calculator.hpp"

Calculator::Calculator() : _sum(0) {}

Calculator::~Calculator() {}

int Calculator::add(int value) {
    _sum += value;
    return _sum;
}

void Calculator::reset() {
    _sum = 0;
}

int Calculator::getCurrent() const {
    return _sum;
}

3.2 OC 桥接层(核心)

CalculatorBridge.h(纯 OC 接口 - 暴露给业务层)

objectivec 复制代码
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

/// 计算器桥接类 - OC 调用入口
@interface CalculatorBridge : NSObject

/// 初始化计算器
- (instancetype)init;

/// 累加数值并返回当前总和
- (NSInteger)addNumber:(NSInteger)number;

/// 重置计算器
- (void)reset;

/// 获取当前总和
- (NSInteger)currentSum;

@end

NS_ASSUME_NONNULL_END

CalculatorBridge.mm(OC++ 实现 - 桥接核心)

objectivec 复制代码
#import "CalculatorBridge.h"
#import "Calculator.hpp"   // ⭐ 引入 C++ 头文件

// 类扩展 - 存放 C++ 对象指针
@interface CalculatorBridge () {
    Calculator *_cppCalculator;   // ⭐ 持有 C++ 对象指针
}
@end

@implementation CalculatorBridge

- (instancetype)init {
    self = [super init];
    if (self) {
        // ⭐ 手动创建 C++ 对象
        _cppCalculator = new Calculator();
        NSLog(@"✅ 计算器已初始化");
    }
    return self;
}

// ⭐ 核心:OC 方法 → C++ 方法调用
- (NSInteger)addNumber:(NSInteger)number {
    if (!_cppCalculator) return 0;
    int result = _cppCalculator->add((int)number);
    return (NSInteger)result;
}

- (void)reset {
    if (_cppCalculator) {
        _cppCalculator->reset();
    }
}

- (NSInteger)currentSum {
    if (!_cppCalculator) return 0;
    return (NSInteger)_cppCalculator->getCurrent();
}

// ⭐ 关键:手动释放 C++ 对象
- (void)dealloc {
    if (_cppCalculator) {
        delete _cppCalculator;      // ⭐ ARC 不会自动释放 C++ 对象
        _cppCalculator = nullptr;
        NSLog(@"🗑️ C++ 对象已释放");
    }
}

@end

3.3 OC 业务层:使用桥接

MainViewController.m(业务代码,纯 OC)

objectivec 复制代码
#import "MainViewController.h"
#import "CalculatorBridge.h"   // ⭐ 只引入 OC 桥接头文件

@interface MainViewController ()
@property (nonatomic, strong) CalculatorBridge *calculator;
@property (weak, nonatomic) IBOutlet UILabel *resultLabel;
@end

@implementation MainViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // ⭐ 完全 OC 风格,感知不到 C++ 的存在
    self.calculator = [[CalculatorBridge alloc] init];
    
    // 累加测试
    [self.calculator addNumber:10];   // → 10
    [self.calculator addNumber:20];   // → 30
    [self.calculator addNumber:5];    // → 35
    
    NSInteger sum = [self.calculator currentSum];
    self.resultLabel.text = [NSString stringWithFormat:@"总和: %ld", (long)sum];
    // 输出: 总和: 35
}

- (IBAction)onAddButtonClick:(id)sender {
    NSInteger random = arc4random_uniform(100);
    NSInteger result = [self.calculator addNumber:random];
    NSLog(@"➕ 加 %ld,当前总和: %ld", (long)random, (long)result);
}

- (IBAction)onResetButtonClick:(id)sender {
    [self.calculator reset];
    self.resultLabel.text = @"已重置";
}

@end

3.4 进阶:带 C++ 回调的桥接

当 C++ 算法需要通知 OC 层(如进度回调)时:

Calculator.hpp(增加回调支持)

cpp 复制代码
#pragma once
#include <functional>

class Calculator {
public:
    // 回调类型定义
    using ProgressCallback = std::function<void(int percent)>;
    
    Calculator();
    ~Calculator();
    
    void setProgressCallback(ProgressCallback callback);
    void longRunningTask();   // 耗时任务,会触发回调
    
private:
    ProgressCallback _callback;
};

CalculatorBridge.mm(处理回调)

objectivec 复制代码
#import "CalculatorBridge.h"
#import "Calculator.hpp"

@interface CalculatorBridge () {
    Calculator *_cppCalculator;
}
@end

@implementation CalculatorBridge

- (void)startLongTask {
    __weak typeof(self) weakSelf = self;
    
    // 设置 C++ 回调
    _cppCalculator->setProgressCallback([weakSelf](int percent) {
        // ⭐ 回到主线程更新 UI
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakSelf updateProgress:percent];
        });
    });
    
    // 启动耗时任务(在子线程执行)
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        _cppCalculator->longRunningTask();
    });
}

- (void)updateProgress:(int)percent {
    self.progressView.progress = percent / 100.0;
    self.progressLabel.text = [NSString stringWithFormat:@"%d%%", percent];
}

@end

3.5 类型转换速查表

OC 类型 C++ 类型 转换方式
NSInteger int (int)value
NSString* std::string std::string([str UTF8String])
std::string NSString* [NSString stringWithUTF8String:str.c_str()]
NSArray<T*>* std::vector<T> 遍历 [array enumerateObjectsUsingBlock:]
NSData* const char* (const char*)[data bytes]

转换示例:

objectivec 复制代码
// OC → C++
NSString *name = @"John";
std::string cppName = std::string([name UTF8String]);

// C++ → OC
std::string cppResult = "Hello";
NSString *ocResult = [NSString stringWithUTF8String:cppResult.c_str()];

四、关键注意事项

序号 注意点 说明
1 文件后缀 桥接文件必须用 .mm,不能用 .m
2 头文件隔离 桥接类的 .h 不能引入 C++ 头文件
3 内存管理 C++ 对象必须手动 new/delete
4 类型转换 注意 OC 与 C++ 类型的相互转换
5 线程安全 C++ 回调若涉及 UI,需切回主线程
6 编译设置 Xcode 默认支持,无需额外配置

五、总结

复制代码
┌────────────────────────────────────────────────────────────┐
│                    集成流程一图流                          │
├────────────────────────────────────────────────────────────┤
│                                                            │
│  1. 写 C++ 算法    →  Calculator.hpp + Calculator.cpp    │
│                         ↓                                 │
│  2. 写 OC 桥接类    →  CalculatorBridge.h (纯 OC 接口)   │
│                         ↓                                 │
│  3. 实现桥接 .mm    →  CalculatorBridge.mm               │
│     - #import "Calculator.hpp"                           │
│     - 持有 C++ 对象指针 `_cppCalculator`                 │
│     - OC 方法里调用 `_cppCalculator->方法()`             │
│     - dealloc 里 `delete _cppCalculator`                 │
│                         ↓                                 │
│  4. 业务层调用      →  只 #import "CalculatorBridge.h"   │
│                         ↓                                 │
│  5. 编译运行        →  Xcode 自动处理 .cpp + .mm         │
│                                                            │
└────────────────────────────────────────────────────────────┘

核心要诀: .mm 是唯一的跨语言接触点,负责"翻译"和"生命周期管理",OC 业务层完全透明。这就是 iOS 上的 JNI!