如何创建可与Swift互操作且含析构函数的C++类?
问题:带析构函数的C++类与Swift互操作失败
问题场景
需要创建一个可与Swift互操作且带有析构函数的C++类,示例代码如下:
C++代码
namespace Name { class Foo { public: Foo() = default; Foo(uint32_t i); // 实现放在.cpp文件中 ~Foo(); // 实现放在.cpp文件中 }; }
Swift代码
import cxxLib let bar = Name.Foo(2)
遇到的错误
编译时触发如下错误:
main.swift: error: 'Foo' is unavailable: non-trivial C++ class with trivial ABI is not yet available in Swift let bar = Name.Foo(2) ^~~ __ObjC.cv:3:19: note: 'Foo' has been explicitly marked unavailable here public struct Foo { ^
移除析构函数后代码可正常运行,但C标准库中的类(必然带析构函数)通过创建模板类型别名即可在Swift中使用,因此需要找到实现自定义带析构函数C类与Swift互操作的方案。环境:Windows系统,Swift 5.10。
解决方案
方法1:使用PIMPL(指针实现)模式包装类
通过将类的核心逻辑隐藏在内部实现类中,对外暴露的类仅持有指针,让其ABI变为平凡类型,同时保留析构函数的资源清理能力:
修改后的C++代码
namespace Name { // 前置声明内部实现类 class FooImpl; class Foo { public: Foo() = default; explicit Foo(uint32_t i); ~Foo(); // 析构函数用于销毁内部Impl指针 // 禁用拷贝(如需支持可手动实现) Foo(const Foo&) = delete; Foo& operator=(const Foo&) = delete; // 支持移动语义 Foo(Foo&&) noexcept; Foo& operator=(Foo&&) noexcept; private: FooImpl* impl; // 指向实际实现的指针 }; }
在.cpp文件中实现Foo的构造、析构和移动操作,内部FooImpl包含原有的业务逻辑和析构逻辑。这种方式下,对外的Foo类ABI平凡,Swift可正常访问,析构函数也能正确清理内部资源。
方法2:创建C风格包装接口
通过纯C函数封装C类的创建、销毁和操作,Swift直接调用C接口绕开对C类的直接限制:
C包装头文件(foo_wrapper.h)
#ifndef FOO_WRAPPER_H #define FOO_WRAPPER_H #include <stdint.h> // 不透明指针,隐藏C++类细节 typedef struct Foo Foo; // 创建Foo实例 Foo* Foo_Create(uint32_t i); // 销毁Foo实例 void Foo_Destroy(Foo* foo); #endif
C++实现文件(foo_wrapper.cpp)
#include "foo_wrapper.h" #include "foo.h" // 包含原Foo类的头文件 struct Foo { Name::Foo inner; // 原C++类实例 }; Foo* Foo_Create(uint32_t i) { return new Foo{Name::Foo(i)}; } void Foo_Destroy(Foo* foo) { delete foo; }
Swift调用代码
import Foundation // 导入C包装库 cImport { #include "foo_wrapper.h" } // 使用包装接口,defer确保资源释放 let bar = Foo_Create(2) defer { Foo_Destroy(bar) }
方法3:利用模板别名技巧
参考C++标准库的兼容方式,为自定义类创建模板类型别名,让Swift识别为可互操作类型:
C++头文件修改
namespace Name { class Foo { public: Foo() = default; Foo(uint32_t i); ~Foo(); }; // 创建模板别名 template<typename T = void> using FooAlias = Foo; }
Swift调用代码
import cxxLib let bar = Name.FooAlias(2)
该技巧依赖Swift C++互操作的具体实现,可能存在版本兼容性差异,需结合当前Swift版本测试验证。
内容的提问来源于stack exchange,提问作者bquack-l
相关产品推荐
相关产品推荐

