Matlab Engine for C - Passing Arrays
2 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Hi, I am trying to make a simple Matlab Engine app, and am running into difficulties working out how to pass arrays. The code is as follows....
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "engine.h"
void myFun(double t2[], int arrayLen, char *funName);
void myFun(double t2[], int arrayLen, char *funName) {
static Engine *ep;
static double engStatus = 0;
mxArray *result = NULL;
double * sum;
mxArray *T = NULL;
//char funName[50] = "debugMfile";
if(engStatus == 0) {
ep = engOpen(""); // Connect to MATLAB engine
if(ep==0) {
printf("Connecton to Matlab Engine failed\n");
}
else {
printf("Connecton to Matlab Engine succeeded!\n");
engEvalString(ep,"cd('/home/arwel/Documents/MATLAB/mNestFiles');");
engStatus = 1;
}
}
//Create variables for the inputs
T = mxCreateDoubleMatrix(1,arrayLen,mxREAL);
memcpy((void *)mxGetPr(T), (void *)t2, 4);
//Put these variables in the Matlab workspace
engPutVariable(ep,"time",T);
//Now call the function..
//(N.B. eventually aim to do this based on 'funName')
engEvalString(ep,"total = debugMfile(time)");
//Get the return value..
result = engGetVariable(ep,"total");
sum = (double *)mxGetData(result);
printf("The answer is %f \n",sum);
engClose(ep);
}
int main() {
double time[4] = {1, 2, 3, 4};
int arrayLen = 4;
char funName[50] = "debugMfile";
myFun(time, arrayLen, funName);
return(0);
}
..with a 'toy' Matlab test function that looks like this...
function total = debugMfile(time)
total = sum(time);
save debugMfileVars.mat
end
But, the result I get back into C is always 0.000, and if I examine 'debugMfileVars.mat' it's just...
>> a = load('debugMfileVars.mat')
a =
struct with fields:
time: [0 0 0 0]
total: 0
>>
Clearly I've missed a step or mixed up something with pointers here somewhere but can't spot it. What have I missed here?? Cheers, Arwel
0 comentarios
Respuestas (4)
Jan
el 19 de Jul. de 2017
Editada: Jan
el 19 de Jul. de 2017
You do not want to display the pointer, but its contents:
double * sum;
sum = (double *)mxGetData(result);
printf("The answer is %f \n", *sum);
// ^
You do not want to copy 4 bytes, but 4 doubles:
memcpy((void *)mxGetPr(T), (void *)t2, 4 * sizeof(double))
// ^^^^^^^^^^^^^^^^
0 comentarios
James Tursa
el 19 de Jul. de 2017
Editada: James Tursa
el 19 de Jul. de 2017
In addition to what Jan has written, you will want to destroy the mxArray variables after using them in myFun so you don't have a memory leak. And since this is an Engine app and not a mex routine, you should check to see that those mxArray pointers are not NULL before you use them. E.g.,
//Create variables for the inputs
T = mxCreateDoubleMatrix(1,arrayLen,mxREAL);
if( T ) {
memcpy( mxGetPr(T), t2, arrayLen*sizeof(*t2) );
} else {
/* do something to handle error */
}
//Put these variables in the Matlab workspace
engPutVariable(ep,"time",T);
mxDestroyArray(T);
//Now call the function..
//(N.B. eventually aim to do this based on 'funName')
engEvalString(ep,"total = debugMfile(time)");
//Get the return value..
result = engGetVariable(ep,"total");
if( result ) {
/* should add code here to check result for correct class and size etc */
sum = (double *)mxGetData(result);
} else {
/* do something to handle error */
}
printf("The answer is %f \n",*sum);
mxDestroyArray(result);
0 comentarios
Arwel
el 20 de Jul. de 2017
1 comentario
James Tursa
el 20 de Jul. de 2017
Editada: James Tursa
el 20 de Jul. de 2017
In C (and by default in C++), all function arguments are passed by value. So anything in the argument list that doesn't match the signature exactly will be converted to the exact signature type first and then that is what is actually passed to the function ... a copy (or converted copy) of the value. This all happens automatically as part of the compiling process. Some conversions (like int to double) can be done with no problem, but other conversions (like double to int pointer) cannot be done and will cause a compile error. But the compiler will always attempt to do the conversion automatically if it can (and it is allowed by the language).
The signature for memcpy is:
void *memcpy(void *str1, const void *str2, size_t n)
Object pointers passed into those 1st & 2nd arguments will get automatically converted to void pointers. Btw the same would be true even if I directly assigned an object pointer to a variable that was of type void pointer ... the conversion happens automatically. Since you get the conversion that direction for free in C/C++, I typically don't include the conversion explicitly in my code since I think it clutters things up and makes the code a bit harder to read. However, it doesn't hurt anything to put the conversion in there explicitly, so if you like it go ahead and leave it in. (Side Note: That 3rd argument would be automatically converted as well if you didn't pass in a size_t type).
The other way is different. Converting a void pointer to an object pointer requires explicit casting in C++.
Ver también
Categorías
Más información sobre Call MATLAB from C en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!