How to Declare, Create, and Use Method Pointers in Swift

How to initialize and use function pointer in Swift

To assign the closure to the property you have to remove the parentheses

self.funcPointer = self.func1

The subsequent error

self' used in method call 'func1' before all stored properties are initialized

can be fixed by declaring funcPointer implicit unwrapped optional

internal final var funcPointer: (() -> Void)!

Does Swift not work with function pointers?

Apple has made function pointers available as of beta 3, however they can only be referenced not called.

Using Swift with Cocoa and Objective-C

Function Pointers


C function pointers are imported into Swift as CFunctionPointer<Type>, where Type is a
Swift function type. For example, a function pointer that has the type int (*)(void) in C
is imported into Swift as CFunctionPointer<() -> Int32>

Beta 3 Release Notes (PDF)

Function pointers are also imported now, and can be referenced and passed around. However,
you cannot call a C function pointer or convert a closure to C function pointer type.

Declare a pointer to a property and pass it as inout param into func in Swift?

After discussion in comments, the question is intended to be specifically how to work with UnsafeMutablePointer to achieve the result, and less about the best way to achieve the result.

It's important that the entirety of the code from the point of acquiring the pointer to using it be scoped within withUnsafeMutablePointer. Because it comes down to selecting between two arrays, and then passing one of them via an alias to someFunc, you don't know which pointer has to be kept live, so you have to keep them both live. Otherwise your program will likely crash when Swift invalidates it.

The proper and safe way to achieve the desired effect with pointers is like this:

func pointerSolution()
{
var sourceArray1 = [1, 2, 3, 4]
var sourceArray2 = [5, 6]

func someFunc(_ someArray: inout [Int]) {
someArray.indices.forEach { someArray[$0] = 0 }
}

let someCase = true // just for the sake of compiling a concrete case

//usage code
withUnsafeMutablePointer(to: &sourceArray1)
{ src1 in
withUnsafeMutablePointer(to: &sourceArray2)
{ src2 in
// Substitute appropriate type for `Int`
let arrayPtr: UnsafeMutablePointer<[Int]>
if someCase {
arrayPtr = src1
// Some additional code that may or may not involve arrayPtr
} else {
arrayPtr = src2
// Some additional code that may or may not involve arrayPtr
}
someFunc(&arrayPtr.pointee)
}
}

print("sourceArray1 = \(sourceArray1)")
print("sourceArray2 = \(sourceArray2)")
}

If you have to do this is in multiple places, or just want to clean up the syntactic bloat of nesting withUnsafeMutablePointer blocks, you can provide a helper function:

func withUnsafeMutablePointers<T, R>(
to value1: inout T,
and value2: inout T,
_ body: (UnsafeMutablePointer<T>, UnsafeMutablePointer<T>) throws -> R) rethrows -> R
{
try withUnsafeMutablePointer(to: &value1)
{ ptr1 in
try withUnsafeMutablePointer(to: &value2)
{ ptr2 in
try body(ptr1, ptr2)
}
}
}

Then where you use it, you have one level of nesting:

func pointerSolution()
{
var sourceArray1 = [1, 2, 3, 4]
var sourceArray2 = [5, 6]

func someFunc(_ someArray: inout [Int]) {
someArray.indices.forEach { someArray[$0] = 0 }
}

let someCase = true // just for the sake of compiling a concrete case

//usage code
withUnsafeMutablePointers(to: &sourceArray1, and: &sourceArray2)
{ src1, src2 in
// Substitute appropriate type for `Int`
let arrayPtr: UnsafeMutablePointer<[Int]>
if someCase {
arrayPtr = src1
// Some additional code that may or may not involve arrayPtr
} else {
arrayPtr = src2
// Some additional code that may or may not involve arrayPtr
}
someFunc(&arrayPtr.pointee)
}

print("sourceArray1 = \(sourceArray1)")
print("sourceArray2 = \(sourceArray2)")
}

If you want to live dangerously, you can do this:

func dangerousPointerSolution()
{
var sourceArray1 = [1, 2, 3, 4]
var sourceArray2 = [5, 6]

func someFunc(_ someArray: inout [Int]) {
someArray.indices.forEach { someArray[$0] = 0 }
}

let someCase = true // just for the sake of compiling a concrete case

//usage code
let address: Int
if someCase {
address = withUnsafeMutablePointer(to: &sourceArray1) { Int(bitPattern: $0) }
// Some additional code that may or may not involve address
} else {
address = withUnsafeMutablePointer(to: &sourceArray2) { Int(bitPattern: $0) }
// Some additional code that may or may not involve address
}
someFunc(&(UnsafeMutablePointer<[Int]>(bitPattern: address)!).pointee)

print("sourceArray1 = \(sourceArray1)")
print("sourceArray2 = \(sourceArray2)")
}

Note the pointer conversion through Int. This is because when withUnsafeMutablePointer returns, it invalidates the pointer $0 internally, and if you were to just return $0, the pointer that is returned by withUnsafeMutablePointer is also invalidated. So you have to trick Swift into giving you something you can use outside of withUnsafeMutablePointer. By converting it to an Int, you're basically saving off the valid address as a numeric value. Swift can't invalidate it. Then outside of withUnsafeMutablePointer you have to convert that Int address back into a pointer, which UnsafeMutablePointer<T> has an initializer to do (after all, you can imagine an embedded system with memory mapped I/O. You'd need to read/write to a specific address to do I/O.) Any time you have to trick the compiler into letting you do something, it should be a big red flag that maybe you shouldn't be doing that. You may still have good reasons, but at the very least, it should cause you to question them, and consider alternatives.

It's important that you don't use address to reconstruct another pointer outside of this scope. In this specific example, it remains a valid address within the function scope only because it's an address for local values that are referred to after the pointer is used. When those values go out of scope, using any pointer to them becomes a problem. If they were properties of a class letting the address escape outside of the scope of the class would be a problem when the instance is deinitialized. For a struct the problem happens sooner since it's likely it would end up being used on a copy of the struct rather than on the original instance.

In short, when using pointers, keep them as local as possible, and be sure they, or anything that can be used to reconstruct them without the original Swift "object" they point to, don't escape outside the context in which you know for sure that they are valid. This isn't C. You don't have as much control over the lifetime of allocated memory. Normally in Swift you don't have to worry about it, but when you do use pointers, it's actually harder to reason about their validity than it is in C for the very reason that you don't get to specify when allocated memory becomes invalid. For example, in Swift, it's not guaranteed that a locally allocated instance of a class will remain "live" through the end of the scope. In fact, it's often deinitialized immediately after its last use, even though there may be more code after in the same scope. If you have a pointer to such an object, even when you are still the same scope, you may now be pointing to deinitialized memory. Swift even has to provide withExtendedLifetime to deal with such cases. That's why Swift tries to limit their use solely within the withUnsafePointer family of functions. That's the only context that it can guarantee their validity. There are other contexts in which they would be valid, but the compiler can't prove that they are.

use variable to store function in swift as pointer function in Obj-C or C++

To solve the error

Class 'MenuScene' has no initializers

you have two options: change the declaration of animationFunction to make it an Optional or create a designated initializer for MenuScene where you assign a value to the non-Optional `animationFunction.

To solve the second error of incompatible types, you need to change the declaration of animationFunction since currently it's type is TimeInterval and not a function type. From the error message it seems you want a function of type (TimeInterval)->(), namely one that accepts a single input parameter of type TimeInterval and returns Void.

To fix both errors, simply modify the declaration of animationFunction to make it Optional and have the required function type:

private var animationFunction: ((TimeInterval)->())?

how to call a function that takes a function pointer argument in Swift?

customCopyDescription needs to be a free function, not a method. When I copied your code into Xcode I got the error message only when customCopyDescription was inside a class, not otherwise.

Once placeholder return values are added and customCopyDescription is placed at file scope, the code compiles without a problem

How to create a pointer in Swift?

(Assuming I understand what you're asking for....)

Try the following code in a playground. It should print "99" three times.

class Row {
var rowNumber = 0
}

var rows = [Row]()

let testRow = Row()
testRow.rowNumber = 1

rows.append(testRow)

let selectedRow = rows[0]
selectedRow.rowNumber = 99

print(testRow.rowNumber)
print(selectedRow.rowNumber)
print(rows[0].rowNumber)

By default, there's no copying of objects as part of an assignment statement. If it were a struct, that would be different.


Adding a bit for completeness:

If you want a similar effect with scalar values instead of objects, Swift supplies various types of wrappers.

let intPointer = UnsafeMutablePointer<Int>.allocate(capacity: 8)  // Should be 1, not 8 according to comment re: docs
let other = intPointer
other.pointee = 34

print(intPointer.pointee)

(Warning: I haven't used these wrappers for anything except experimenting in a playground. Don't trust it without doing some research.)

Function pointer in swift

If you use func RunLoopSourceScheduleRoutine() as the callback
then it needs to be a global function, not an instance method.

If you define the callback as a closure then it needs to be marked
as a pure C callback:

let runLoopSourceScheduleRoutine: @convention(c) (UnsafeMutableRawPointer?, CFRunLoop?, CFRunLoopMode?) -> Void =
{ (info, rl, mode) in

let obj = Unmanaged<RunLoopSource>.fromOpaque(info!).takeUnretainedValue()
// ...
}

Alternatively, pass a closure expression to that the compiler
infers the type as a C callback:

var context = CFRunLoopSourceContext(version: 0, info: UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()) ,
retain: nil,
release: nil,
copyDescription: nil,
equal: nil,
hash: nil,
schedule: { (info, rl , mode) in

let obj = Unmanaged<RunLoopSource>.fromOpaque(info!).takeUnretainedValue()
// ...
}, cancel: nil,
perform: nil)

Note also that you have to call the method on obj, not on self.
I would recommend GCD instead of performSelector(), this allows
the compiler to check that the method is called with correct
arguments:

let obj = Unmanaged<RunLoopSource>.fromOpaque(info!).takeUnretainedValue()
let theContext = RunLoopContext(withSource: obj, andLoop: rl!)
DispatchQueue.main.async {
obj.myMethod(theContext)
}

Simple Pointer Operations in Swift?

Yes-ish.

You can't do it exactly as you've attempted in the question. It won't compile. Swift won't let you directly access the address of a value like this. At the end of the day, the reason is mostly because there's simply no good reason to do so.

We do see the & operator in Swift however.


First of all, there is the inout keyword when declaring function parameters:

func doubleIfPositive(inout value: Float) -> Bool {
if value > 0 {
value *= 2
return true
}
return false
}

And to call this method, we'd need the & operator:

let weMadeARadian = doubleIfPositive(&pi)

We can see it similarly used when we have a function which takes an argument of type UnsafeMutablePointer (and other variants of these pointer structs). In this specific case, it's primarily for interoperability with C & Objective-C, where we could declare a method as such:

bool doubleIfPositive(float * value) -> bool {
if (value > 0) {
value *= 2;
return true;
}
return false;
}

The Swift interface for that method ends up looking somethin like this:

func doubleIfPositive(value: UnsafeMutablePointer<Float>) -> Bool

And calling this method from Swift actually looks just like it did before when using the inout approach:

let weMadeARadian = doubleIfPositive(&pi)

But these are the only two uses of this & operator I can find in Swift.

With that said, we can write a function that makes use of the second form of passing an argument into a method with the & operator and returns that variable wrapped in an unsafe mutable pointer. It looks like this:

func addressOf<T>(value: UnsafeMutablePointer<T>) -> UnsafeMutablePointer<T> {
return value
}

And it behaves about as you'd expect from your original code snippet:

var i: Int = 1
var iPtr = addressOf(&i)
iPtr.memory = 2
print(i) // prints 2

Sample Image


As noted by Kevin in the comments, we can also directly allocate memory if we want.

var iPtr = UnsafeMutablePointer<Int>.alloc(1)

The argument 1 here is effectively the mount of space to allocate. This says we want to allocate enough memory for a single Int.

This is roughly equivalent to the following C code:

int * iPtr = malloc(1 * sizeof(int));

Sample Image



BUT...

If you're doing any of this for anything other than interoperability with C or Objective-C, you're most likely not Swifting correctly. So before you start running around town with pointers to value types in Swift, please, make sure it's what you absolutely need to be doing. I've been writing Swift since release, and I've never found the need for any of these shenanigans.

In SwiftUI how to define a function pointer to the HStack or VStack constructor

Ternary operator actually is not applicable to SwiftUI types as they all value-types with generics so result in constructed different type entities and cannot be assigned to one variable.

Instead possible approach for your case is something like

@ViewBuilder var content: some View {
Text("Text")
Image(systemName: "checkmark")
}

var body: some View {
if isHorizontal {
HStack{ content }
} else {
VStack{ content }
}
}


Related Topics



Leave a reply



Submit