I'm trying to figure out how to call variadic C functions that write to pointers from Swift, such as vsscanf
, but I don't understand how to actually construct the list of pointers to Swift variables.
I figure that if I have a string, I can get an UnsafePointer<CChar>
and call vsscanf
on it, but... how do I tell it where to actually write the data? How do I construct the CVaListPointer
to pass to vsscanf
?
var a: Int
var b: Float
"(5, 3.14)".withCString{buffer in
let r = vsscanf(buffer, "(%d, %f)", /* how do I put a and b here? */)
}
Basically, doing the same thing as here (C):
#include <stdio.h>
#include <stdarg.h>
int parse(const char *buffer, char *format, ...)
{
va_list args;
va_start(args, format);
int result = vsscanf(buffer, format, args);
va_end(args);
return result;
}
int main(int argc, char const *argv[])
{
int a;
float b;
char s[] = "(5, 3.14)";
int r = parse(s, "(%d, %f)", &a, &b);
printf("a: %d, b: %f\n", a, b);
// "a: 5, b: 3.140000"
return 0;
}
CodePudding user response:
From the documentation on CVarArgs:
To create a wrapper for the
c_api
function, write a function that takesCVarArg
arguments, and then call the imported C function using thewithVaList(_:_:)
function.Swift only imports C variadic functions that use a
va_list
for their arguments. C functions that use the...
syntax for variadic arguments are not imported, and therefore can’t be called usingCVarArg
arguments.
Your wrapper function could look like:
func vsscanfSwiftWrapper(
buffer: UnsafePointer<CChar>,
format: UnsafePointer<CChar>,
_ arguments: CVarArg...
) -> CInt {
withVaList(arguments) { vaList in
vsscanf(buffer, format, vaList)
}
}
CodePudding user response:
Like this:
var a: Int = 0
var b: Float = 0
withUnsafePointer(to: &a) { pointerToA in
withUnsafePointer(to: &b) { pointerToB in
withVaList([pointerToA, pointerToB]) { va_list in
"(5, 3.14)".withCString { buffer in
let r = vsscanf(buffer, "(%d, %f)", va_list)
}
}
}
}
print(a)
print(b)
outputs
5
3.14