用于 CFunctionPointer 到 Swift 闭包的 Objective-C 包装器 [英] Objective-C Wrapper for CFunctionPointer to a Swift Closure

查看:21
本文介绍了用于 CFunctionPointer 到 Swift 闭包的 Objective-C 包装器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在玩 Swift 并注意到 Swift 不允许创建 CFFunctionPointers.它只能传递和引用现有的.

I am playing with Swift and noticed that Swift does not allow to create CFFunctionPointers. It can only pass around and reference existing ones.

例如 CoreAudio 需要 CFunctionPointer 到某些回调,因此我不能使用纯 Swift.

As for example CoreAudio requires CFunctionPointer to certain callbacks therefore I cannot use pure Swift.

所以我需要在这里使用一些 Objective-C 蹦床或包装器,它们将 Swift 闭包作为参数以及原始回调原型,然后可以分配为回调,但实际操作发生在 Swift 中而不是目标-C.

So I need to use some Objective-C trampoline or wrapper here that takes a Swift Closure as a parameter as well as the original callback prototype and then can be assigned to be the callback, but the actually action happens in Swift and not Objective-C.

我该怎么做?

此类包装器的一些示例代码将帮助我了解如何以灵活的方式将目标 C 中的 Swift 代码用于此类目的,以解决 Swift 无法创建 CFunctionPointers 的问题.

Some example code for such a wrapper would help me to understand how I can use Swift code from objective C for such purposes in a flexible way to work around Swift not being able to create CFunctionPointers.

是的,我知道我可以在需要时在 Objective-C 中写东西.我想用纯 Swift 来做这件事,作为一项学习练习,将我的一个应用程序移植到 Swift(使用了很多 CoreAudio/CoreVideo 框架).

Yes, I know I can just write stuff when needed in Objective-C. I want to do it in pure Swift as a learning exercise porting one of my apps to Swift (uses a lot of CoreAudio/CoreVideo framework).

推荐答案

我需要定义这个回调:

typedef void (*MIDIReadProc) ( const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon );

我想尽可能少地使用 Objective-C.

and I wanted to use Objective-C as least as possible.

这是我的方法:

MIDIReadProcCallback.h

MIDIReadProcCallback.h

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

typedef void (^OnCallback)(const MIDIPacketList *packetList);

@interface MIDIReadProcCallback : NSObject

+ (void (*)(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon))midiReadProc;
+ (void)setOnCallback:(OnCallback)onCallback;

@end

MIDIReadProcCallback.m

MIDIReadProcCallback.m

#import "MIDIReadProcCallback.h"

static OnCallback _onCallback = nil;

static void readProcCallback(const MIDIPacketList *pktlist, void *refCon, void *connRefCon) {
    if (_onCallback) {
        _onCallback(pktlist);
    }
}

@implementation MIDIReadProcCallback

+ (void (*)(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon))midiReadProc {
    return readProcCallback;
}

+ (void)setOnCallback:(OnCallback)onCallback {
    _onCallback = onCallback;
}

@end

然后你可以注册 MIDIReadProcCallback.midiReadProc 作为回调并设置处理程序 MIDIReadProcCallback.setOnCallback({ (packetList: MIDIPacketList) in ... })

Then you can register MIDIReadProcCallback.midiReadProc as callback and set handler MIDIReadProcCallback.setOnCallback({ (packetList: MIDIPacketList) in ... })

这篇关于用于 CFunctionPointer 到 Swift 闭包的 Objective-C 包装器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆