如何在Swift中使用带有私有析构函数的C++类?
这个问题我之前在项目里踩过坑,Swift和C的交互逻辑确实和Objective-C有不少不一样的地方,尤其是在内存管理这块的检查更严格。你碰到的情况很典型:Objective-C对C类的私有成员限制没那么死板,只要你通过合法的静态方法来创建、销毁对象,它就不会拦你;但Swift的C++桥接机制会默认要求被桥接的类必须有可访问的析构函数——因为Swift自身的内存管理依赖于能正确释放对象,当它发现析构函数是私有的,就会直接拒绝桥接这个类型,所以直接用肯定不行。
那怎么解决呢?最靠谱的办法是用Objective-C++做一层中间包装,把C++类的接口封装成Swift能识别的Objective-C类,具体步骤如下:
1. 保留你的C++类不变
先确保原来的C++类逻辑没问题,静态创建/销毁的机制保留:
// MyClass.h class MyClass { public: static MyClass *New() { return new MyClass(); } static void Delete(MyClass *object) { delete object; } // 示例业务方法 void doSomething() { // 这里写你的业务逻辑 } private: MyClass() {} ~MyClass() {} };
2. 编写Objective-C++包装类
需要分两个文件:纯Objective-C的头文件(让Swift能桥接),和Objective-C的实现文件(处理C逻辑)。
头文件(MyWrapper.h)
这个文件里不能有任何C++代码,必须是纯Objective-C语法:
#import <Foundation/Foundation.h> @interface MyWrapper : NSObject // 把C++类的方法暴露成Objective-C方法 - (void)doSomething; @end
实现文件(MyWrapper.mm)
后缀用.mm表示这是Objective-C文件,可以直接包含C头文件并调用:
#import "MyWrapper.h" #include "MyClass.h" @interface MyWrapper () // 用assign保存C++实例指针,因为它不是Objective-C对象 @property (nonatomic, assign) MyClass *cppInstance; @end @implementation MyWrapper - (instancetype)init { self = [super init]; if (self) { // 在init里调用C++的静态方法创建实例 _cppInstance = MyClass::New(); } return self; } - (void)dealloc { // 在dealloc里调用C++的静态方法销毁实例 if (_cppInstance) { MyClass::Delete(_cppInstance); _cppInstance = nullptr; } [super dealloc]; } - (void)doSomething { // 转发调用到C++实例的方法 _cppInstance->doSomething(); } @end
3. 在Swift中使用包装类
现在你可以直接在Swift代码里导入桥接头(如果还没配置桥接头,记得在Build Settings里设置Objective-C Bridging Header),然后像用普通Objective-C类一样使用MyWrapper:
let wrapper = MyWrapper() wrapper.doSomething() // 不用手动销毁,Swift的ARC会自动调用MyWrapper的dealloc,进而销毁C++实例
为什么这个方法可行?
因为Swift只和Objective-C的包装类交互,完全不知道底层的C类细节。包装类把C对象的创建(init里调用MyClass::New())和销毁(dealloc里调用MyClass::Delete())都封装好了,既遵守了C++类的私有成员限制,又满足了Swift对内存管理的要求。
内容来源于stack exchange

