【问题标题】:Error call function (instance member cannot be used)错误调用函数(不能使用实例成员)
【发布时间】:2018-04-21 00:01:07
【问题描述】:

这不是懒惰的重复原因,我也有一个问题: “不能从捕获上下文的闭包中形成 C 函数指针”

在我的主类中,我有“detectChangeMidi”,但在这段代码中,当我尝试调用一个函数时,我不明白为什么我不能。 (我也不能使用 var,我班的任何东西)

我不是 swift 方面的专家,然后尝试向我解释发生了什么。 我使用 CoreMidi 库。

更新:

我用极简代码替换代码以获得更好的意图。

import Foundation
import CoreMIDI

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        gestionMidi()
        //...
    }

    func gestionMidi() {
        //...
        let midiNotif:MIDINotifyProc = detectChangeMidi
        MIDIClientCreate("Swift3 Test Client" as CFString, midiNotif, nil, &midiClient)
        //...
    }

    func plop(){
        print("bla bla bla")
    }

    let detectChangeMidi: @convention(c) (UnsafePointer<MIDINotification>, UnsafeMutableRawPointer?) -> Swift.Void =
    { midiNotification,unkown   in
        var notification = midiNotification.pointee

        self.plop()     //problem here
        //...
    }
}

【问题讨论】:

  • 你不能在实例属性声明中引用 self。
  • 没有self.,我也有一个问题:实例成员'plop'不能用于'ViewController'类型;您的意思是改用这种类型的值吗?
  • @matt 而且它不是重复的,如果我使用“lazy var ...”我也有一些问题
  • 即使你没有明确地说self,你也隐含地指代了self。你不能这样做。它重复的;这是完全相同的规则。唯一的区别是您的初始化程序是一个匿名函数体。您可以轻松地将其简化为一个非常简单的测试用例,如下所示:class MyClass { func myMethod() {}; let myProperty = { myMethod() } } 这就是您正在做的事情,这是非法的。这是有据可查的。
  • 您是对的,您不能将lazy 用于C 函数指针。但是,只需以其他方式表达这个 C 函数指针——而不是作为实例属性。无论如何,convention(c) 适用于 types,而不适用于 declarations,因此您要做什么并不明显。如果您尝试调用 convention(c) 函数,只需调用它即可。如果您尝试编写 convention(c) 函数,则必须用 C 编写它。

标签: swift function swift3


【解决方案1】:

问题出在范围上,我可以从错误消息中判断。

另外需要注意的是,您正在关闭执行 plop(),这需要 self.plop()

还有midiNotification,unkown in - unkown 似乎是一个错字。

检查您声明函数本身的位置。从这个 sn-p 很难理解你的声明范围是什么。

【讨论】:

  • 我在主帖中更新了我的代码。最好了解发生了什么?对于形式: MIDINotifyProc = (UnsafePointer, UnsafeMutableRawPointer?) -> Void
【解决方案2】:

您的整个议程都被误导了;您可以尝试做什么并不明显。您不能将属性或函数声明为convention(c),也不能引用self。但你不需要!如果您的目标是将函数作为参数传递给需要 C 函数指针的位置,则只需传递该函数。无论如何,如果您改为拨打MIDIClientCreateWithBlock(_:_:_:),您在 Swift 中的使用会更轻松。

【讨论】:

  • 可以声明@convention(c) (arg_types...) -&gt; return_type类型的属性——但是它不能捕获上下文,即你不能使用self。对我来说,这看起来像是 stackoverflow.com/q/33260808/1187415 的副本。
  • @MartinR 哇。一如既往地感谢。是否有为此提交的错误? — 但是,我仍然认为,OP 不需要需要 声明这样的属性,并且调用 MIDIClientCreateWithBlock(_:_:_:) 而不是过时的 MIDIClientCreate(_:_:_:_:) 会更好。
  • 什么错误? MIDIClientCreate() 接受一个 C 函数回调,您可以传递一个文字闭包,或一个全局函数,或(如这里)一个约定(c)闭包。但是那个 C 回调不能捕获上下文(因为它只是一个函数指针)。 – MIDIClientCreateWithBlock 是对的,它需要一个可以捕获上下文的块。
  • @MartinR 够公平的。
  • 非常感谢,我明白我的代码和 MIDIClientCreateWithBlock(::_:) 有什么问题,我没有问题,真的更好更简单。
猜你喜欢
  • 2019-02-15
  • 2017-06-06
  • 1970-01-01
  • 2017-05-27
  • 2020-01-23
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
相关资源
最近更新 更多