Reputation: 384
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.
Upvotes: 1
Views: 539
Reputation: 539715
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) { ... }
Upvotes: 0