user1965822
user1965822

Reputation: 13

How to call C function with two-dimensional array argument in Swift?

In my swift program, I have successfully called a C function with 1-dim array argument. But when I try to call a C function with 2-dim array argument in Swift, it prompts an error as below:

'[([(Double)])]' is not convertible to 'UnsafeMutablePointer<(Double, Double, Double, Double, Double)>'

Here is my calling in swift:

var tSet  = [[Double]](count: 18, repeatedValue: [Double](count: 5,repeatedValue: Double(0.0)))
getTrainSet(sub_xlist, tSet)

and my C function definition:

void getTrainSet(const double *ax, double trainSet[18][5])

It seems something wrong with the initialization of 2-dim array in Swift. Anyone could help? Thank you.

Upvotes: 1

Views: 1169

Answers (2)

rintaro
rintaro

Reputation: 51911

void getTrainSet(const double *ax, double trainSet[18][5])

is translated to Swift as:

func getTrainSet(ax: UnsafePointer<Double>, trainSet: UnsafeMutablePointer<(Double, Double, Double, Double, Double)>)

Solution1

Make an Array of (Double, Double, Double, Double, Double):

var sub_xlist: Double = 0
var tSet = [(Double,Double,Double,Double,Double)](count: 18, repeatedValue: (0,0,0,0,0))
getTrainSet(&sub_xlist, &tSet)

and get the results like:

tSet[1].3 // equivalent to `tSet[1][3]` in C

Solution2

In C, double trainSet[18][5] is just a buffer of 90 (18 * 5) doubles. You can make [Double] with 90 elements and pass it as UnsafeMutablePointer:

var sub_xlist: Double = 0
var tSet = [Double](count: 18 * 5, repeatedValue: 0)
getTrainSet(&sub_xlist, UnsafeMutablePointer(tSet))

And you can get the results like:

let row = 1
let col = 3
tSet[row * 5 + col] // equivalent to `tSet[row][col]` in C

Upvotes: 1

Kostiantyn Koval
Kostiantyn Koval

Reputation: 8483

This C function has this type in Swift

void getTrainSet(const double *ax, double trainSet[2][2]) // C
getTrainSet(ax: UnsafePointer<Double>, 
            trainSet: UnsafeMutablePointer<(Double, Double)>)  //Swift

To convert var to UnsafePointer you have to use & when passing it to function

var sub_xlist = 10.0
getTrainSet(&sub_xlist)  

Two dimensional array are converted to a Array of Tuples in Swift. Second dimension determinate how many elements will be in the Tuple
Example:

double a[2][2] // In C
[(Double, Double)]() // In Swift

Int a[18][3] // In C
[(Int, Int, Int)]() // In Swift

UnsafeMutablePointer<(Double, Double)> - is an array of Tuples with type (Double, Double) In your example trainSet is an Array of Tuples with 5 Double elements

Solution :

var sub_xlist = 10.0
var p: UnsafeMutablePointer<(Double, Double, Double, Double, Double)> = nil
var tuples  = [(Double, Double, Double, Double, Double)]()
getTrainSet(&sub_xlist, &tuples)
getTrainSet(&sub_xlist, p)

Read more here Interacting with C APIs

Upvotes: 1

Related Questions