Copying dynamic array to MxArray object using memcpy in c++

Hi I am trying to copy a n*m matrix defined by dynamic memory allocation to mxArray, and send it to matlab the matrix is sent right in size but false in values. I appreciate if anyone can help me to find what is wrong. here is the code
double **dataDMA;
int m = 3, n = 3, c = 0;
mxArray *matDDMA;
dataDMA = (double **)calloc(sizeof(double *), m); // number of columns
for (int i = 0; i < m; ++i)
{
dataDMA[i] = (double *)calloc(sizeof(double), n); // number of rows
}
printf("\nMatrix created by Dynamic Memory Allocation:\n");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
dataDMA[i][j] = c+1;
printf("%g ", dataDMA[i][j]);
c = c + 1;
}
printf("\n");
}
matDDMA=mxCreateDoubleMatrix(m, n, mxREAL);
if (matDDMA == NULL)
{
printf("Unable to create mxArray matDDMA.\n");
return(EXIT_FAILURE);
}
memcpy((void *)mxGetPr(matDDMA), (void *)dataDMA, m*n *sizeof(double));
engPutVariable(ep, "matDDMA", matDDMA);
engEvalString(ep, "matDDMA");

 Respuesta aceptada

James Tursa
James Tursa el 11 de Abr. de 2018
Editada: James Tursa el 11 de Abr. de 2018
Two fundamental problems:
1) You can't guarantee that successive calls to calloc( ) will produce memory segments that are adjacent to each other in memory. So the entire concept of using a single memcpy to copy such memory as one big block is non-conforming. If might happen to work if you are lucky, and then the next time the program will bomb because you weren't lucky. If you want to copy it all as one single block of memory, then you need to allocate it as such. E.g.,
dataDMA = (double **)calloc(sizeof(double *), m); // number of columns
dataDMA[0] = (double *)calloc(sizeof(double), n*m); // entire block of double memory
for (int i = 1; i < m; ++i) // <-- start loop indexing at 1
{
dataDMA[i] = dataDMA[i-1] + n; // next column is n elements over
}
Then, when you are done with this memory you only have two free( ) calls to make:
free(dataDMA[0]);
free(dataDMA);
2) The dataDMA pointer points to the column address array, not to the double data itself. So your memcpy source address is wrong. It should be this:
memcpy(mxGetPr(matDDMA), dataDMA[0], m*n *sizeof(double)); // don't need (void *) here

6 comentarios

James Tursa
James Tursa el 11 de Abr. de 2018
Editada: James Tursa el 11 de Abr. de 2018
When do you call engClose(ep)? Are you closing the Engine before you get a chance to see the plot? Note that you do not have to call engClose(ep) at the end of your program. That will ensure that the Engine stays running even after your program exits and all of the variables & plots will remain intact. This means you will have to manually close it instead, but that is OK. Are you getting no plot, or a blank plot, or ...?
ShimShim
ShimShim el 16 de Abr. de 2018
Editada: James Tursa el 16 de Abr. de 2018
Thanks for your answer James. I appreciate your help.
I tried importing a .txt file, consisting of a 512*512 matrix, whose data is stored in a 2D array defined by Dynamic Memory Allocation. Then I used an imshow command to see this CT image.
I still have the previous problem, that the matrix is right in size, but not right in values. The values are scaled down, and the imshow command shows a black image.
Here is the code:
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include"engine.h"
int main(void)
{
//linking to matlab
Engine *ep;
//Call engOpen with a NULL string.
//This starts a MATLAB process on the current host using the command "matlab".
if (!(ep = engOpen("")))
{
fprintf(stderr, "\nCan't start MATLAB engine\n");
return EXIT_FAILURE;
}
double **data1DMA;
int mm = 512, nn = 512;
FILE *input_file;
char in_file[100];
printf("Enter input file name\n");
scanf("%s", in_file);
inputfile = fopen(in_file, "r");
if (!(input_file))
{
printf("File does not exist.\n");
exit(EXIT_FAILURE);
}
data1DMA = (double **)calloc(sizeof(double *), mm); // number of columns
data1DMA[0] = (double *)calloc(sizeof(double *), nn*mm); // entire block of double memory
for (int i = 1; i < mm; ++i)
{
data1DMA[i] = data1DMA[i - 1] + nn; // next column is nn element over
}
for (int i = 0; i < nn; i++)
{
for (int j = 0; j < mm; j++)
{
fscanf(input_file, "%f ", &data1DMA[i][j]);
}
}
mxArray *matdata1DMA = mxCreateDoubleMatrix(mm, nn, mxREAL);
memcpy(mxGetPr(matdata1DMA), data1DMA[0], mm*nn * sizeof(double)); // doesn't need void
engPutVariable(ep, "matdata1DMA", matdata1DMA);
engEvalString(ep, "A=matdata1DMA");
engEvalString(ep, "imshow(A)");
free(data1DMA[0]);
free(data1DMA);
mxDestroyArray(matdata1DMA);
engClose(ep);
return 0;
}
"... but not right in values ..."
That would typically mean you are not reading in the values correctly. It appears you are trying to read the file as a text file, so you need to open it as a text file and not a binary file. Try changing this
inputfile = fopen(in_file, "r");
to this
inputfile = fopen(in_file, "rt");
Then, in your C code you should print out a few values after you fscanf them in to check.
I tried "rt", but it still is not working. I see, the problem is with the for loop, where I am trying to scan data to the array. But I cannot figure out what needs to be changed.
Does the first value scan in correctly? I would work on just getting this first number to work properly, and then move on to the rest of the file.
James, I changed all doubles to float, also used mxArray* matdata1DMA = mxCreateNumericMatrix(mm, nn, mxSINGLE_CLASS, mxREAL); instead of mxArray* matdata1DMA = mxCreateNumericMatrix(mm, nn, mxREAL); which worked.
The only matter was with the image which was flipped, so I changed the indexes in the for loop to data1DMA[i][j] to data1DMA[j][i] when scanning as below;
for (int i = 0; i < mm; i++)
{
for (int j = 0; j < nn; j++)
{
fscanf(input_file, "%f ",&data1DMA[j][i]);
}
}
Thanks a lot for your help.

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre C Shared Library Integration en Centro de ayuda y File Exchange.

Preguntada:

el 10 de Abr. de 2018

Comentada:

el 17 de Abr. de 2018

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by