You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Swift中暴露含纯虚方法的C++监听器类并实现约束?

实现C++纯虚监听器向Swift的暴露与回调转发

当然有可行方案!核心思路是通过Objective-C++适配器模式,把Swift实现的逻辑桥接到C++的纯虚类上。下面是分步实现的详细方案,配合代码示例:

1. 定义Objective-C协议对应C++监听器

首先创建一个Objective-C协议,映射C++ ResultListener的纯虚方法,这样Swift可以通过遵守该协议来实现回调逻辑:

// TestResultListenerProtocol.h
#import <Foundation/Foundation.h>

@protocol TestResultListenerProtocol <NSObject>
- (void)listenResult:(NSInteger)result;
@end

2. 编写Objective-C++适配器类

这个适配器类是关键:它继承C的test::ResultListener,同时持有一个遵守上述Objective-C协议的对象,负责把C侧的回调转发给Swift实现的逻辑。注意文件后缀必须是.mm(表示Objective-C++文件):

头文件

// ResultListenerAdapter.h
#import "TestResultListenerProtocol.h"
#include "ResultListener.h"

@interface ResultListenerAdapter : NSObject
- (instancetype)initWithListener:(id<TestResultListenerProtocol>)listener;
- (test::ResultListener*)cppListener;
@end

实现文件

// ResultListenerAdapter.mm
#import "ResultListenerAdapter.h"

// 继承C++纯虚类的适配器实现
class CppResultListenerAdapter : public test::ResultListener {
public:
    CppResultListenerAdapter(id<TestResultListenerProtocol> listener) : _listener(listener) {}
    
    // 重写纯虚方法,转发给Objective-C/Swift对象
    void listenResult(int result) override {
        [_listener listenResult:(NSInteger)result];
    }
private:
    __weak id<TestResultListenerProtocol> _listener; // 用weak避免循环引用
};

@implementation ResultListenerAdapter {
    CppResultListenerAdapter* _cppAdapter;
}

- (instancetype)initWithListener:(id<TestResultListenerProtocol>)listener {
    self = [super init];
    if (self) {
        _cppAdapter = new CppResultListenerAdapter(listener);
    }
    return self;
}

- (test::ResultListener*)cppListener {
    return _cppAdapter;
}

// 释放C++对象
- (void)dealloc {
    delete _cppAdapter;
}

@end

3. 包装C++的FunctionExecutor类

同样用Objective-C编写FunctionExecutor的包装类,暴露给Swift调用,内部负责把Swift传入的协议对象转换成C适配器:

头文件

// TestFunctionExecutor.h
#import <Foundation/Foundation.h>
#import "TestResultListenerProtocol.h"

@interface TestFunctionExecutor : NSObject
- (void)setListener:(id<TestResultListenerProtocol>)listener;
@end

实现文件

// TestFunctionExecutor.mm
#import "TestFunctionExecutor.h"
#include "FunctionExecutor.h"
#import "ResultListenerAdapter.h"

@implementation TestFunctionExecutor {
    test::FunctionExecutor* _cppExecutor;
    ResultListenerAdapter* _listenerAdapter;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _cppExecutor = new test::FunctionExecutor();
    }
    return self;
}

- (void)setListener:(id<TestResultListenerProtocol>)listener {
    // 创建适配器并传给C++对象
    _listenerAdapter = [[ResultListenerAdapter alloc] initWithListener:listener];
    _cppExecutor->setListener(_listenerAdapter.cppListener);
}

- (void)dealloc {
    delete _cppExecutor;
}

@end

4. 配置桥接文件

在项目的Swift桥接文件(通常命名为[项目名]-Bridging-Header.h)中导入Objective-C头文件,让Swift可以访问这些类和协议:

#import "TestResultListenerProtocol.h"
#import "TestFunctionExecutor.h"

5. Swift侧实现与调用

现在Swift可以直接遵守协议实现监听器,并传给包装后的TestFunctionExecutor:

// 实现监听器
class MyResultHandler: NSObject, TestResultListenerProtocol {
    func listenResult(_ result: Int) {
        print("Swift收到C++回调结果:\(result)")
        // 这里可以处理UI或业务逻辑
    }
}

// 使用示例
let executor = TestFunctionExecutor()
let handler = MyResultHandler()
executor.setListener(handler)

注意事项

  • 内存管理:适配器中使用__weak修饰Objective-C对象,避免C++对象和Swift对象之间的循环引用。
  • 线程安全:如果C++库在非主线程调用监听器,Swift中若涉及UI操作,需要手动切换到主线程(比如用DispatchQueue.main.async)。
  • 文件后缀:所有包含C++代码的Objective-C文件必须使用.mm后缀,否则编译器会报错。

内容的提问来源于stack exchange,提问作者Marcos Lopez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:54:01