New @Convention(C) in Swift 2: How to Use It

New @convention(c) in Swift 2: How can I use it?

You no longer need to create a CFunctionPointer in Swift 2. Instead, you can annotate your type by calling convention, in this case c, and use it directly.

typealias CFunction = @convention(c) (UnsafeMutablePointer<Void>, Float) -> Int
let bar = unsafeBitCast(foo, CFunction.self)

The relevant bits of the @convention description in the Type Attributes section of The Swift Programming Language are:

The c argument is used to indicate a C function reference. The function value carries no context and uses the C calling convention.

What are some specific examples of how to use the Swift 2 @convention(c) type annotation?

let cFunction : @convention(c) (Int, Int) -> Int = { $0 + $1 }

Swift2 @convention(c) with char* and type**

check this 'self explanatory' example

let str = "A"
var c = str.utf8.map { (c) -> CChar in
return CChar(c)
}[0]
print(c, c.dynamicType) // 65 Int8

var p = UnsafeMutablePointer<CChar>.alloc(1)
print(p.memory, p.memory.dynamicType) // 0 Int8
p.memory = 65

func modify(pp: UnsafeMutablePointer<UnsafeMutablePointer<CChar>>)->Void {
print(pp.memory.memory, pp.memory.memory.dynamicType)
}

let pp = withUnsafeMutablePointer(&p){ $0 }
print(pp, pp.dynamicType) // 0x0000000119bbf750 UnsafeMutablePointer<UnsafeMutablePointer<Int8>>

modify(pp) // 65 Int8

...

p.dealloc(1)
modify(pp) // -107 Int8
// -107 is some 'random' value, becase the memory there was dealocated!!

UnsafePoiner<CChar> is const char * while
UndafeMutablePointer<CChar> is char *
etc ...

Swift + C functions

Yes, it should be possible. In Swift 2, one can send a Swift closure as a parameter to C, when C expects a function pointer. In your case, you have wrapped it in a struct, so an addition of '@convention(c)' to explicitly state that it's C, might help.

see examples here
new-conventionc-in-swift-2-how-can-i-use-it

Using Function pointer callback methods in Swift

As the error message says, you have to use @convention(c) in order to define the swift function or closure that is interoperable with other C functions. Try this:

typealias MethodHandler = @convention(c) (
_ msg_data_ptr : UnsafeMutablePointer<msg_data>?,
_ types: UnsafePointer<Int8>?,
_ argv : UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>?,
_ argc: Int32,
_ user_data: UnsafeMutablePointer<Int8>?
) -> Void


let handler: MethodHandler = { msg_data_ptr, types, argv, argc, user_data in
...
}

add_handler_new("handler", handler, nil, 0, 1)

Using CFNotificationCallback in Swift, or, @convention(c) blocks in Swift

Letting the compiler infer the closure's signature works fine:

let callback: CFNotificationCallback = { center, observer, name, object, info in
//works fine
}

Trying to specify @convention(c) in the closure's declaration gives an error:

let callback: CFNotificationCallback = { @convention(c) (center: CFNotificationCenter?, observer: UnsafeRawPointer?, name: CFString?, object: UnsafeRawPointer?, info: CFDictionary?) -> Void in
//Attribute can only be applied to types, not declarations.
}

It seems like what's going on is that when you manually declare the closure's type, it forces the compiler to use that exact type. But that's technically a closure declaration and not a type declaration, so the @convention attribute isn't allowed. When the compiler is allowed to infer the closure's type (from the type of the variable it is being stored in), it can infer the attribute too.



Related Topics



Leave a reply



Submit