Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Receiving multidimensional array from C api, how to handle in Swift?

Tags:

arrays

c

ios

swift

I use a C library in my Swift application and I cannot figure out how to get the multidimensional array that the C method is supposed to return.

I receive this from the C API:

struct resultArray
{
    double *data;
    int size[2];
};

Where:

size = the matrix size, a two element array with the number of rows and number of columns

data = the matrix data

In swift I can do the following to get the size:

let numRows = Int(results.size.0)
let numColoumns = Int(results.size.1)

But I don't understand how to get the matrix so that I can iterate through it? I tried the following:

let matrixResult = results.data.memory

This seems to return only a double value because matrixResult becomes a Double.

Then I tried this:

let matrixResult = results.data

Which makes the matrixResult an:

UnsafeMutablePointer<Double>

I expect to receive a matrix as specified in the C library documentation. Then I want to iterate through this matrix and get the values from the first row and put it in a Swift array... Does somebody know what I am missing here?

like image 559
juppy Avatar asked May 10 '16 08:05

juppy


1 Answers

There is no matrix type in C. Assuming that data is a pointer to the contiguous matrix elements stored as an array, you would copy the first row to a Swift array with

let firstRow = Array(UnsafeBufferPointer(start: results.data, count: numColumns))

and the entire "matrix" to a nested Swift array with

let matrix = (0 ..< numRows).map { row in
    Array(UnsafeBufferPointer(start: results.data + numColumns * row, count: numColumns))
}

Alternatively (and this is similar to what Melifaro suggested), you can create an array of pointers pointing into the matrix rows:

let matrix = (0 ..< numRows).map { row in
    UnsafeBufferPointer(start: results.data + numColumns * row, count: numColumns)
}

This still allows to address arbitrary elements in a matrix-like fashion

 let element = matrix[row][col]

but does not copy the data. Of course this requires that the matrix data is valid throughout the use of matrix, as the memory is not managed by Swift.

like image 142
Martin R Avatar answered Oct 16 '22 09:10

Martin R