Swift 如何将CFunctionPointer转换为EventHandlerUPP?

Swift 如何将CFunctionPointer转换为EventHandlerUPP?,swift,callback,event-handling,Swift,Callback,Event Handling,我有一个名为Foo_C_Func的C函数,需要将其用作回调函数。应用程序的其余部分用Swift编码。据我所知,下面的代码应该可以工作,但是我得到了一个编译器错误 // typealias makes our function signature easier to read typealias Sig = ( EventHandlerCallRef, EventRef, UnsafeMutablePointer<Void>) -> OSStatus // We need

我有一个名为Foo_C_Func的C函数,需要将其用作回调函数。应用程序的其余部分用Swift编码。据我所知,下面的代码应该可以工作,但是我得到了一个编译器错误

// typealias makes our function signature easier to read 

typealias Sig = ( EventHandlerCallRef, EventRef, UnsafeMutablePointer<Void>) -> OSStatus

// We need to make a CFunctionPointer to the C function 

var ptr = UnsafeMutablePointer<Sig>.alloc(1)
ptr.initialize( Foo_C_Func )
let c_ptr = COpaquePointer( ptr )

let proc_ptr = CFunctionPointer<Sig>( c_ptr ) as EventHandlerProcPtr

// now we should be able to create the EventHandlerUPP

let handler_upp = NewEventHandlerUPP( proc_ptr )
//typealias使函数签名更易于阅读
typealias Sig=(EventHandlerCallRef、EventRef、UnsafeMutablePointer)->OSStatus
//我们需要制作一个指向C函数的CFunctionPointer
var ptr=unsafemeutablepointer.alloc(1)
ptr.initialize(Foo_C_Func)
设c_ptr=COpaquePointer(ptr)
让proc_ptr=CFunctionPointer(c_ptr)作为EventHandlerProcPtr
//现在我们应该能够创建EventHandlerUPP了
let handler\u upp=NewEventHandlerUPP(proc\u ptr)
尝试生成此文件失败,出现以下错误:

架构x86_64的未定义符号:

“_Foo_C_Func”,引用自:

__演示中的TTOFSC10Foo_C_函数ftvss14opaquepointers_gvss20unsafemtablepointert____VSs5Int32

“\u NewEventHandlerUPP”,引用自:

__演示中的TFC17DemocfMS0_FT_S0_u

ld:找不到架构x86_64的符号

我还注意到,当我将鼠标悬停在最后一行时,Xcode工具提示将NewEventHandlerUpp的返回类型显示为(EventHandlerProcPtr),而不是EventHandlerProcPtr


我是做错了,还是无法在Swift中创建一个EventHandlerUPP

我为用户MAH发布这篇文章,尽管我已经放弃了原来的项目。以下代码在Swift 3中编译。除此之外,我还没有检查它是否有效

import Carbon

func hotkey_callback( _:EventHandlerCallRef?, _ event:EventRef?, _ context:UnsafeMutablePointer<Void>? ) -> OSStatus {
    // Do stuff
    return noErr
}

let handler_ref_ptr = UnsafeMutablePointer<EventHandlerRef?>( allocatingCapacity: 1 )

let spec_ptr = UnsafeMutablePointer<EventTypeSpec>( allocatingCapacity: 1 )

spec_ptr.pointee = EventTypeSpec( eventClass: OSType( kEventClassKeyboard ), eventKind:  UInt32( kEventHotKeyPressed ) )

let hotkey_callback_pointer = hotkey_callback as! EventHandlerUPP

let status = InstallEventHandler( GetEventDispatcherTarget(), hotkey_callback_pointer, 1, spec_ptr, nil, handler_ref_ptr )
进口碳
func热键\回调(\ uU:EventHandlerCallRef?,\ uEvent:EventRef?,\ uContext:UnsafeMutablePointer?)->OSStatus{
//做事
返回noErr
}
let handler_ref_ptr=UnsafeMutablePointer(分配容量:1)
let spec_ptr=UnsafeMutablePointer(分配容量:1)
spec_ptr.pointee=EventTypeSpec(eventClass:OSType(kEventClassKeyboard),eventKind:UInt32(KeventThotKeypressed))
让热键回调指针=热键回调为!EventHandlerUPP
让status=InstallEventHandler(GetEventDispatcherTarget(),热键回调指针,1,规范ptr,nil,处理程序ref\ptr)

如果您使用的是Swift 3,这里有一个备选答案。Swift 2与Swift 3不同,前者很糟糕,而后者可用

let hotkey_callback: EventHandlerUPP = { _, _, _ in
    // Do stuff
    return noErr
}

var handler: EventHandlerRef? = nil

var spec = EventTypeSpec( 
    eventClass: OSType(kEventClassKeyboard), eventKind:  UInt32(kEventHotKeyPressed) 
)

let status = InstallEventHandler( 
    GetEventDispatcherTarget(), hotkey_callback, 1, &spec, nil, &handler 
)

请注意,我们现在可以使用“&”来避免手动分配指针,并注意遵守非正式的“EventHandlerUPP”协议现在是显式的,不需要手动声明每个参数的类型。阅读起来容易多了:)

到目前为止,我还无法在Swift 3中找到解决方法。向苹果发送了一份关于它的错误报告,因为它也缺少文档。我很确定这些天(Swift 2和更高版本)你可以直接使用该函数(在你的C头文件中声明为“extern”,如果Swift抱怨该类型,则使用“as?EventHandlerUPP”)。此外,你真的想用C而不是Swift来实现这一点吗?我相信在我最初的Xcode项目中,一旦Swift 2发布,我就重构了不存在的C文件。如果我没记错的话,现在可以使用Swift函数来创建这样的指针。我在2.0中通过Swift轻松地实现了这一点,但Swift 3似乎改变了一切。我不能使用
作为?EventHandlerUPP
@MAH,我得到了一个旧文件,在那里我可以毫不费力地编译它,但我还没有测试它。虽然这个文件确实可以编译,但不幸的是它在
上的
EXC\u BAD\u指令
使热键回调指针=热键回调为!EventHandlerUPP
我隐约记得我的原始版本中存在一些访问问题。您正在使用的功能是全局的还是“公共的”?谢谢您的帮助。是的。此问题仅限于Swift 3。我想这可能是苹果的一个缺陷。但是将公共函数强制转换为EventHandlerUPP似乎不起作用。是的,可能是个bug。作为一种解决方法,使用“让热键回调指针=unsafeBitCast(热键回调,EventHandlerUPP.self)”有效吗?刚刚尝试过,看起来是相同的崩溃。非常令人沮丧。看起来这样行得通。我认为这是一个苹果不断改变哪些值是可选的,哪些值不是的问题。现在我想它的设置是Swift3。谢谢