Using C functions in Swift that take functions as arguments -
i'm writing wrapper around c mathematical library. every function takes 1 or 2 functions arguments. however, arguments child functions (as parent functions) not swifty -hence wrapper.
i've cleaned example code show 3 main pieces: c-library function, desired swift function passed wrapper (body not shown, wrapping around c-library function), , required c function form.
//c library function, calls passed function dozens, hundreds or thousands of times, each time changes data provided in p, , uses output x //the swift arrays passed pointers, , length of , x array m , n respectively returnvalue = clibraryfunc(passedfunc, &p, &x, int32(m), int32(n), int32(itmax), &opts, &info, &work, &covar, &adata) //i create swift function (internals myriad of things takes inputs p , adata , 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 length of p (so m well) //and assumes adata length same x length (n) //obviously, ifer m , n p.count , x.count in 0..<n { x[i] = p[0] + p[1]*adata[i] + p[2]*pow(adata[i], 2) } } //and wrapper "convert" -internally- form c library function requires: func requiredc(p: unsafemutablepointer<double>?, x: unsafemutablepointer<double>?, m: int32, n: int32, adata: unsafemutablepointer<void>?) { //same thing, using pointers, , uglier //first, have bitcast void double let adatadouble : unsafemutablepointer<double> = unsafebitcast(adata, to: unsafemutablepointer<double>.self) in 0..<int(n) { x![i] = p![0] + p![1]*adatadouble[i] + p![2]*pow(adatadouble[i], 2) } }
addition
i should add have access c source code, possibly add dummy parameters (possibly find way pass context in). given docs seem indicate 1 can't grab context c function pointer, may of no use.
(note: following example uses swift 3 on xcode 8 beta 2.)
your question c functions taking c function argument, let reduce question problem. here simple c function takes single argument again c function takes pointer array of doubles , 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 imported swift as
func cfunc(_ func: (@convention(c) (unsafemutablepointer<double>?, int32) -> swift.void)!)
here @convention(c)
declares block have c-style calling conventions. in particular, swift can pass global function or closure not capture context.
a simple example swift wrapper is
func swiftyfunc(passedfunc: (@convention(c) (unsafemutablepointer<double>?, int32) -> void)) { cfunc(passedfunc) }
which can use this:
func functiontopass(values: unsafemutablepointer<double>?, count: int32) { let bufptr = unsafebufferpointer(start: values, count: int(count)) elem in bufptr { print(elem) } } swiftyfunc(passedfunc: functiontopass)
or closure argument:
swiftyfunc { (values, count) in let bufptr = unsafebufferpointer(start: values, count: int(count)) elem in bufptr { print(elem) } }
Comments
Post a Comment