hboon
(Hwee-Boon Yar)
1
Given (this is the libxml2 C library):
void xmlSetGenericErrorFunc(void * ctx, xmlGenericErrorFunc handler)
//Function type: xmlGenericErrorFunc
//void xmlGenericErrorFunc(void * ctx, const char * msg, ...)
I'm trying to do:
private func handleValidationError(ctx: OpaquePointer, msg: UnsafePointer<CChar>, args: CVarArg...) {
NSLog("xx validation error handler called")
}
then:
xmlSetGenericErrorFunc(nil, handleValidationError)
and I'm getting this:
cannot convert value of type '(OpaquePointer, UnsafePointer, CVarArg...) -> ()' (aka '(OpaquePointer, UnsafePointer, CVarArg...) -> ()') to expected argument type 'xmlGenericErrorFunc?' (aka 'Optional')
I suppose I need to do something like this instead:
xmlSetGenericErrorFunc(nil, OpaquePointer(handleValidationError)) //I can't figure out how to create an OpaquePointer instance here
How should I write and pass in the callback?
Joe_Groff
(Joe Groff)
2
You aren't going to be able to interface with this API from Swift, unfortunately, since Swift cannot use C variadic functions. You'll need to write a C wrapper function to interface with the API and then call into that from Swift.
hboon
(Hwee-Boon Yar)
3
Ah. Just for the sake of education. If the callback isn't a variadic function, how would we get it to work? (I couldn't find any docs or anything online that showed how to do it).
Joe_Groff
(Joe Groff)
4
Normally, what you can do is create a C function pointer by specifying a function variable with @convention(c) in Swift:
func add(x: Int, y: Int) -> Int { return x + y }
let addp: @convention(c) (Int, Int) -> Int = add
If you need to pass this into C as a non-function pointer, you can unsafeBitCast it:
let addRawPointer = unsafeBitCast(add, to: UnsafeRawPointer)
2 Likes
Is this why we don’t have printf in Glibc? The %.2f formatter is still one of the few things that C includes, but Swift does not.
Joe_Groff
(Joe Groff)
6
For printf, there is at least also vprintf, an alternative entry point that takes a va_list. You should be able to use the withVaList standard library function to pass down a va_list.
3 Likes
did not even know that existed,, thanks!
Nobody1707
(Nobody1707)
8
Here's an implementation of printf based on vprintf:
import func Foundation.vprintf
@discardableResult
public func printf(_ format: String, _ args: CVarArg...) -> Int {
return Int(withVaList(args) { vprintf(format, $0) })
}
1 Like