SteveFerg
SteveFerg

Reputation: 3570

Using Swift to reference an external C function call that uses pointers

Being new to Xcode, I am trying to make use of an external C call that use pointers, and I’m having difficulty finding a way to reference them in Swift. The original call in C is defined as:

int32 FAR PASCAL swe_calc(double tjd, int ipl, int32 iflag, double *xx, char *serr)

where xx is a pointer to an array of 6 Doubles and serr is a pointer to any error message(s)

Swift sees it as:

int32 swe_calc(tjd: Double, ipl: Int32, iflag: int32, xx: UnsafeMutablePointer<Double>, serr: UnsafeMutablePointer<Int8>)

(from: https://github.com/dwlnetnl/SwissEphemeris/tree/master/SwissEphemeris)

The closest thing I’ve tried that even comes close is:

var serr : UnsafeMutablePointer<Int8> = nil; // returns any error messages from the call
var x  = [Double](count: 6, repeatedValue: 0); // array of 6 doubles returned from the call
var xx : UnsafeMutablePointer<Double> ;

xx = &x
swe_calc(2436647.0003794227, 4, 258, xx, serr)
println("xx = \(x[0]), \(x[1]), \(x[2]), \(x[3]), \(x[4]), \(x[5]), errors (if any)=\(serr)")

The line xx=&x gives the error

Cannot assign a value of type input[(Double)] to a value of type ‘UnsafeMutablePointer’

I need a way to get/reference/use the values returned from xx into an array of 6 doubles, and serr should definitely not be an Int8, but a string instead. (I can get the other Java and C# versions to work, but Swift has me stumped.)

How can I make the swe_calc call to give it what it needs, and get out what I need?

Upvotes: 3

Views: 318

Answers (1)

Martin R
Martin R

Reputation: 539715

You were close. Both UnsafeMutablePointer parameters need an array of the appropriate type passed as "inout argument" with &:

var x  = [Double](count: 6, repeatedValue: 0);
var serr = [Int8](count: 1024, repeatedValue: 0)
let result = swe_calc(2436647.0003794227, 4, 258, &x, &serr)

Of course the arrays must be allocated large enough as expected by the C function.

If that function puts a NUL-terminated error string into the buffer pointed to by serr then you can convert it to a Swift string with:

let errorString = String.fromCString(&serr)

Upvotes: 2

Related Questions