I have the following C function
struct answer* create(struct callbacks *callbacks);
I need to create a struct of function pointers and call this function from Swift
What I have so far is:
func aa(state: CInt, user_data: UnsafeMutablePointer<Void>) {}
func bb(state: CInt, user_data: UnsafeMutablePointer<Void>) {}
struct CallbacksStruct {
let on_aa = aa
let on_bb = bb
}
and I try to call the function like this:
var callbackStruct = CallbacksStruct()
let ans = create(&callbackStruct)
but, without any success
Is it even possible in Swift ?
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
Related
Using Swift 5 (and possibly even earlier), I can easily call C functions from Swift without much ado:
// C function:
error_t cFunction(uint8_t * const outputBuffer, uint8_t const outputBufferMaxSize, uint8_t * const outputBufferUsedBytes);
// called from Swift:
let outputBufferMaxSize: UInt8 = 10
var outputBuffer = [UInt8](repeating: 0, count: Int(outputBufferMaxSize))
var outputBufferUsedBytes: UInt8 = 0
let err = cFunction(&outputBuffer, outputBufferMaxSize, &outputBufferUsedBytes);
The bridging works completely automatic.
Now I want to pass the cFunction to another Swift-func (like a function pointer in C). This only seems to work when I manually perform the translation:
// Swift function with C-style function as parameter
func callcFunction(_ cFunctionAsParameter:(UnsafeMutablePointer<UInt8>?, UInt8, UnsafeMutablePointer<UInt8>?)->error_t) {
let outputBufferMaxSize: UInt8 = 10
var outputBuffer = [UInt8](repeating: 0, count: Int(outputBufferMaxSize))
var outputBufferUsedBytes: UInt8 = 0
let err = cFunctionAsParameter(&outputBuffer, outputBufferMaxSize, &outputBufferUsedBytes);
}
callcFunction(cFunction)
This works, but I have to figure out the UnsafeMutablePointer-logic manually. In fact, if you simply put garbage in the callcFunction declaration, the compiler will spit out an error message telling you the exactly right syntax.
So is there a way to avoid manually doing this declaration?
Like, declaring it using original C style
error_t (* cFunctionAsParameter) (uint8_t * const, uint8_t const, uint8_t * const)
(the above should somehow go into the parameter list of the Swift function declaration) and have the compiler figure out the UnsafeMutablePointer stuff itself, like it does in the first example?
Extended question:
To make matters more complicated, let there be several C functions that differ in the type of an additional single parameter (the first one):
error_t cFunctionFloat(float value, uint8_t * const outputBuffer, uint8_t const outputBufferMaxSize, uint8_t * const outputBufferUsedBytes);
error_t cFunctionInt(int value, uint8_t * const outputBuffer, uint8_t const outputBufferMaxSize, uint8_t * const outputBufferUsedBytes);
which can be used in Swift with the following single declaration:
func callcFunction<T>(_ cFunctionAsParameter:(T, UnsafeMutablePointer<UInt8>?, UInt8, UnsafeMutablePointer<UInt8>?)->error_t){ ... }
Again, it would be nice to have the compiler infer the "translation" automatically.
I am not aware of a pure Swift solution. In the case of a single function you can define a type alias in the C header file
typedef typeof(cFunction) cFunctionType;
so that the Swift function declaration simplifies to
func callcFunction(_ cFunctionAsParameter: cFunctionType) { ... }
It is legal to say this (arr is an Array):
let arrenum = Array(arr.enumerated())
So why isn't it legal to say this?
extension Array {
func f() {
let arrenum = Array(self.enumerated())
// error: type of expression is ambiguous without more context
}
}
EDIT It seems this is a workaround:
extension Array {
func f() {
typealias Tup = (offset:Index, element:Element)
let arrenum = Array<Tup>(self.enumerated())
}
}
But why is that needed? (And is it right?)
This is a known bug (SR-1789). Swift currently has a feature where you can refer to a generic type within its own body without having to repeat its placeholder type(s) – the compiler will infer them for you to be the same as the type of self.
For example:
struct S<T> {
func foo(_ other: S) { // parameter inferred to be `S<T>`.
let x = S() // `x` inferred to be `S<T>`.
}
}
extension S {
func bar(_ other: S) {} // same in extensions too.
}
This is pretty convenient, but the bug you're running into is the fact that Swift will always make this inference, even if it's incorrect.
So, in your example:
extension Array {
func f() {
let arrenum = Array(self.enumerated())
// error: type of expression is ambiguous without more context
}
}
Swift interprets the code as let arrenum = Array<Element>(self.enumerated()), as you're in the body of Array<Element>. This is incorrect, because enumerated() yields a sequence of offset-element tuple pairs – Swift should have inferred Array to be Array<(offset: Int, element: Element)> instead.
One workaround, which you've already discovered, is to explicitly specify the placeholder type in order to prevent the compiler from making this incorrect inference.
extension Array {
func f() {
let arrenum = Array<(offset: Int, element: Element)>(self.enumerated())
}
}
Another possible workaround appears to be using the fully-qualified type, for example:
extension Array {
func f() {
let arrenum = Swift.Array(self.enumerated())
}
}
as it appears Swift doesn't do the same inference for fully-qualified types (I'm not sure if you should rely on this fact though).
Finally it's worth noting that instead of doing a call to Array's initialiser, you could use map(_:) instead to avoid the issue entirely:
extension Array {
func f() {
let arrenum = self.enumerated().map { $0 }
}
}
which, like the initialiser call, will give you back an array of offset-element pairs.
I have a very simple function in C and its pointer gets passed into Swift.
void callback() {
NSLog(#"such pointer…");
}
How can it be invoke in Swift using ONLY the pointer? This is NOT about simply invoking it – it works fine when invoked directly. Tried the following and different variations with signature casting, but it always crashes:
let pointer: UnsafePointer<#convention(c)() -> ()> = UnsafePointer(bitPattern: …)
let callback: #convention(c)() -> () = pointer.memory
Swift.print(callback) // (Function)
callback() // Handling crash with signal 11...
Tried defining Callback type with typedef void(*Callback)(); – same thing:
let pointer: UnsafePointer<Callback> = UnsafePointer(bitPattern: …)
let callback: Callback = pointer.memory
Swift.print(callback) // (Function)
callback() // Handling crash with signal 11...
To check that it actually works and points to the right address I have another Objective-C function, which works as expected when invoked from Swift with the callback pointer.
void invokeCallback(uintptr_t callback) {
((void (*)()) callback)(); // such pointer…
}
The same approach as in Swift: How to call a C function loaded from a dylib should work here.
Example for Swift 3 (assuming that funcPtr is a
UnsafeRawPointer containing the function's address):
// Define function type:
typealias callbackFunc = #convention(c) () -> Void
// Convert pointer to function type:
let callback = unsafeBitCast(funcPtr, to: callbackFunc.self)
// Call function:
callback()
Of course the type alias must match the actual function signature,
and the function needs to be a "pure" C function (not an Objective-C
method).
I'm writing a wrapper around a C mathematical library. Every function takes one or two functions as arguments. However, the arguments for those child functions (as well as the parent functions) are not Swifty -hence the wrapper.
I've cleaned up the example code to just show the three main pieces: the c-library function, the desired Swift function that would be passed to the wrapper (body not shown, but wrapping around the c-library function), and the required C function form.
//C library function, that calls the passed function dozens, hundreds or thousands of times, each time it changes the data provided in p, and uses the output from x
//The Swift arrays are passed as pointers, and the length of the and x array are m and n respectively
returnValue = cLibraryFunc(passedFunc, &p, &x, Int32(m), Int32(n), Int32(itmax), &opts, &info, &work, &covar, &adata)
//I would like to create a Swift function that would look like this (internals could be any myriad of things that takes inputs p and adata and returns data in x:
func desiredSwifty(p: inout [Double], x: inout [Double], m: Int, n: Int, adata: inout [Double]) {
//very simple example
//this example knows the length of p (so m as well)
//and assumes that adata length is the same as the x length (n)
//obviously, it could ifer m and n from p.count and x.count
for i in 0..<n {
x[i] = p[0] + p[1]*adata[i] + p[2]*pow(adata[i], 2)
}
}
//And the wrapper would "convert" it -internally- into the form that the C library function requires:
func requiredC(p: UnsafeMutablePointer<Double>?, x: UnsafeMutablePointer<Double>?, m: Int32, n: Int32, adata: UnsafeMutablePointer<Void>?) {
//same thing, but using pointers, and uglier
//first, have to bitcast the void back to a double
let adataDouble : UnsafeMutablePointer<Double> = unsafeBitCast(adata, to: UnsafeMutablePointer<Double>.self)
for i in 0..<Int(n) {
x![i] = p![0] + p![1]*adataDouble[i] + p![2]*pow(adataDouble[i], 2)
}
}
addition
I should add that I have access to the c source code, so I could possibly add some dummy parameters (possibly to find a way to pass context in). But given that the docs seem to indicate that one can't grab context with a c function pointer, this may be of no use.
(Note: the following example uses Swift 3 on Xcode 8 beta 2.)
Your question is about C functions taking another C function as an argument, so let us reduce the question to that problem. Here is a simple C function which takes a single argument which is
again a C function which takes a pointer to an array of doubles
and an integer count:
// cfunction.h:
void cFunc(void (*func)(double *values, int count));
// cfunction.c:
void cFunc(void (*func)(double *values, int count)) {
double x[] = { 1.2, 3.4, 5,6 };
func(x, 3);
}
This function is imported to Swift as
func cFunc(_ func: (#convention(c) (UnsafeMutablePointer<Double>?, Int32) -> Swift.Void)!)
Here #convention(c) declares the block to have C-style calling
conventions. In particular, from Swift you can pass only a global function or a closure which does not capture any context.
A simple example for a Swift wrapper is
func swiftyFunc(passedFunc: (#convention(c) (UnsafeMutablePointer<Double>?, Int32) -> Void)) {
cFunc(passedFunc)
}
which you can use like this:
func functionToPass(values: UnsafeMutablePointer<Double>?, count: Int32) {
let bufPtr = UnsafeBufferPointer(start: values, count: Int(count))
for elem in bufPtr { print(elem) }
}
swiftyFunc(passedFunc: functionToPass)
or with a closure argument:
swiftyFunc { (values, count) in
let bufPtr = UnsafeBufferPointer(start: values, count: Int(count))
for elem in bufPtr { print(elem) }
}
Do you know that you can get a mutable pointer to a var just by using the & operator? It does the "right thing" on arrays too.
func foo(_ x: UnsafeMutablePointer<Int>) {
print(x)
}
func bar(_ x: UnsafeMutablePointer<Int>) {
print(x)
}
var array = [0]
foo(&array)
var int = 0
bar(&int)
(Tested on Swift 2, but most likely still valid on Swift 3.)
I suspect that this could drastically reduce your need for wrappers.
I am trying to use a C API in Swift that requires me to pass a callback to a function using variadic arguments, i.e.:
extern GEOSContextHandle_t GEOS_DLL initGEOS_r(
GEOSMessageHandler notice_function,
GEOSMessageHandler error_function);
where GEOSMessageHandler is defined as:
typedef void (*GEOSMessageHandler)(const char *fmt, ...);
How should I handle this? I tried to implement an Objective-C class with two class methods defined as follows:
#interface HumboldtCallback : NSObject
+(void)noticeCallback:(const char *)args, ... NS_REQUIRES_NIL_TERMINATION;
+(void)errorCallback:(const char *)args, ... NS_REQUIRES_NIL_TERMINATION;
#end
but Swift does not let me access them. If I define the arguments as void* I can access them from Swift:
var GEOS_HANDLE: COpaquePointer {
let noticeCallbackPointer = HumboldtCallback.noticeCallback;
let errorCallbackPointer = HumboldtCallback.errorCallback;
return initGEOS_r(noticeCallbackPointer, errorCallbackPointer)
}
but the compiler still isn't happy:
Cannot invoke 'initGEOS_r' with an argument list of type '((UnsafeMutablePointer<Void>) -> Void, (UnsafeMutablePointer<Void>) -> Void)'
Should I somehow cast the pointer to the callback function before passing it as a parameter to the init function?
You need to write a C function instead of an objective C method. Unfortunately Swift will convert these into Swift Closure. However you can write a function/method in objective C to return your function pointer. This will stop Swift being able to convert the function to a closure. i.e in your objectiveC header:
void myCallback (const char *fmt, ...);
GEOSContextHandle_t getMyCallback ();
then in the class implement getMyCallback like this:
GEOSContextHandle_t getMyCallback () {
return myCallback;
}
and implement your callback function. In Swift you'll end up with:
initGEOS_r(getMyCallback(), ...)
I believe that you can do this with a plain C header and .c file rather than using an object.