0

It's not a duplicate cause with lazy i have an issu too : "A C function pointer cannot be formed from a closure that captures context"

In my main class I have "detectChangeMidi" but in this code, when I try to call a function I don't understand why I can't. (i can't use var too, anything of my class)

I'm not expert in swift, then try to explain to me what's going one. I use the CoreMidi librarie.

UPDATE :

I replace the code by minimaliste code for better entendement.

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
        //...
    }
}
KasaiJo
  • 130
  • 1
  • 12
  • You cannot refer to self in an instance property declaration. – matt Nov 08 '17 at 14:03
  • Without self., i have an issu too : Instance member 'plop' cannot be used on type 'ViewController'; did you mean to use a value of this type instead? – KasaiJo Nov 08 '17 at 14:07
  • @matt And it s not a duplicate, if i use "lazy var..." i have some problems too – KasaiJo Nov 08 '17 at 14:15
  • Even if you don't say `self` explicitly, you are referring to self implicitly. You cannot do that. It _is_ a duplicate; it is exactly the same rule. The only difference is that your initializer is an anonymous function body. You can easily reduce this to a very simple test case like this: `class MyClass { func myMethod() {}; let myProperty = { myMethod() } }` That is what you are doing and it is illegal. This is very well documented. – matt Nov 08 '17 at 14:38
  • You are right that you can't use `lazy` for a C function pointer. But then just express this C function pointer in some other way — not as an instance property. Anyway, `convention(c)` applies to _types_, not _declarations_, so it is not obvious what you are trying to do. If you are trying to call a `convention(c)` function, just call it. If you are trying to _write_ a `convention(c)` function, you must write it _in C_. – matt Nov 08 '17 at 14:44
  • Almost surely a duplicate of [How to use instance method as callback for function which takes only func or literal closure](https://stackoverflow.com/questions/33260808/how-to-use-instance-method-as-callback-for-function-which-takes-only-func-or-lit) – You cannot use `self` in a convention(c) function, you have to "tunnel" it through a void pointer. – Martin R Nov 08 '17 at 17:52

2 Answers2

1

Your entire agenda here is misguided; it is not at all obvious what you can be trying to do. You cannot declare a property or function as being convention(c) and also refer to self. But you don't need to! If your goal is to pass a function as a parameter where a C pointer-to-function is expected, just pass the function. Anyway you'll have a much easier time in Swift if you call MIDIClientCreateWithBlock(_:_:_:) instead.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • You *can* declare a property of type `@convention(c) (arg_types...) -> return_type` – but then it cannot capture context, i.e. you cannot use `self`. Looks like a duplicate of https://stackoverflow.com/q/33260808/1187415 to me. – Martin R Nov 08 '17 at 17:58
  • @MartinR Whoa. Thanks as always. Is there a bug filed for that? — I still think, however, that the OP does not _need_ to declare such a property, and would do much better to call `MIDIClientCreateWithBlock(_:_:_:)` instead of the outmoded `MIDIClientCreate(_:_:_:_:)`. – matt Nov 08 '17 at 18:05
  • What bug? MIDIClientCreate() takes a C function callback, you can pass a literal closure, or a global function, or (as here) a convention(c) closure. But that C callback cannot capture context (because it is just a function pointer). – You are right with MIDIClientCreateWithBlock, that takes a block which can capture context. – Martin R Nov 08 '17 at 18:22
  • @MartinR Fair enough. – matt Nov 08 '17 at 18:39
  • Thanks you very much, i understand what s the problem with my code and with MIDIClientCreateWithBlock(_:_:_:) i have no problem, is really better and simple. – KasaiJo Nov 09 '17 at 07:51
0

The problem is with the scope as I can judge from the error message.

Also the thing to get attention to is that you're executing plop() in closure, and that requires self.plop().

also midiNotification,unkown in - unkown seems to be a typo.

Check where you declare the function itself. From this snippet it's hard to understand what's your declaration scope.

inokey
  • 5,434
  • 4
  • 21
  • 33
  • I update my code in the main post. It's better for understand what's going on ? And for the form : MIDINotifyProc = (UnsafePointer, UnsafeMutableRawPointer?) -> Void – KasaiJo Nov 08 '17 at 14:01