1

Using the MatLab C API and Go's Cgo package, I'm attempting to read a 24x3000000 matrix inside a mat-file in my Go program. I'm able to successfully read the dimensions of the matrix but how do I access the values inside each cell? (The goal is ultimately to return this matrix as a slice to my Go program.)

var realDataPtr *C.double
var field *C.mxArray

fieldName := C.CString("data")
field = C.mxGetField(pa, 0, fieldName)

rowTotal := C.mxGetM(field) // outputs 24
colTotal := C.mxGetN(field) // outputs 3000000

// get pointer to data in matrix
realDataPtr = C.mxGetPr(field)

// Print every element in the matrix
for row := 0; row < int(rowTotal); row++ {
    for col := 0; col < int(colTotal); col++ {
        // This is where I get stuck
    }
}

For reference, here's the Matrix Library API for C

Adam Soffer
  • 1,614
  • 5
  • 20
  • 36
  • 1
    `mxGetPr` returns a pointer to a regular C array of type `double` with length 24*3000000, stored in column-major order – Amro Nov 02 '14 at 01:48
  • 1
    can you show us the part where you get `field`? Here is an example of reading a variable from a MAT-file: http://stackoverflow.com/a/26241535/97160. If you want I can show another example (in C, I'm afraid I don't know Go), but it would help if you give us a bit more context where the arrays are coming from.. – Amro Nov 02 '14 at 14:28
  • @Amro I've updated my code to show where I get `field`. For some reason `C.mxGetPr(field)` is returning null. According to the docs this means there is no real data. However, I tested `field`using the validation methods [`mxIsDouble`](http://www.mathworks.com/help/matlab/apiref/mxisdouble.html) and [`mxIsNumeric`](http://www.mathworks.com/help/matlab/apiref/mxisnumeric.html) and both return true. – Adam Soffer Nov 02 '14 at 14:52
  • 1
    Oh this could be it. It's not shown in my code but I'm using [`matGetNextVariableInfo`](http://www.mathworks.com/help/matlab/apiref/matgetvariableinfo.html) which according to the docs reads header information only. I probably should be using [`matGetVariable`](http://www.mathworks.com/help/matlab/apiref/matgetvariable.html) – Adam Soffer Nov 02 '14 at 15:04
  • I'm using `matGetNextVariable` instead of `matGetNextVariableInfo` and C.mxGetPr(field) is no long returning null. However I'm still unsure how to access the values without using pointer auto-increment. Go doesn't allow pointer arithmetic. – Adam Soffer Nov 02 '14 at 15:44
  • correct, `matGetNextVariableInfo` gets you only the array header (size, type, etc.. ) but no actual data. Now like I said I don't know Go to answer your question, but can you use something along the lines of [`memcpy`](http://www.cplusplus.com/reference/cstring/memcpy/) in CGo? This seems relevant: https://code.google.com/p/go-wiki/wiki/cgo#Turning_C_arrays_into_Go_slices (you define a Go "slice" header to wrap the underlying C array returned by `mxGetPr`. You can determine the length of the array using `mxGetNumberOfElements`) – Amro Nov 02 '14 at 16:04
  • just to clarify, the length in *bytes* will be `mxGetElementSize(field) * mxGetNumberOfElements(field)` – Amro Nov 02 '14 at 16:11

2 Answers2

1

Matrix data in MATLAB are stored in column major order, which means that the columns of the data are stored in sequential order in memory (this is the opposite to C and similar languages). Thus, if you wanted to access the data sequentially in C (I'm not immediately familiar with Go syntax, unfortunately), you could do the following:

for(col=0;col<colTotal;++col)
{
    for(row=0;row<rowTotal;++row)
    {
        data = realDataPtr[col*rowTotal + row];
    }
}
MrAzzaman
  • 4,734
  • 12
  • 25
1

Untested, since I don't have MatLab. For example,

import (
    "fmt"
    "unsafe"
)

// Print every element in the matrix
ptr := uintptr(unsafe.Pointer(realDataPtr))
for col := 0; col < int(colTotal); col++ {
    for row := 0; row < int(rowTotal); row++ {
        // This is where I get stuck
        elem := *(*float64)(unsafe.Pointer(ptr))
        fmt.Println(elem)
        ptr += 8
    }
}
peterSO
  • 158,998
  • 31
  • 281
  • 276