Matlab Engine for C - Passing Arrays
2 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
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 Kommentare
Antworten (4)
Jan
am 19 Jul. 2017
Bearbeitet: Jan
am 19 Jul. 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 Kommentare
James Tursa
am 19 Jul. 2017
Bearbeitet: James Tursa
am 19 Jul. 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 Kommentare
Arwel
am 20 Jul. 2017
1 Kommentar
James Tursa
am 20 Jul. 2017
Bearbeitet: James Tursa
am 20 Jul. 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++.
Siehe auch
Kategorien
Mehr zu Call MATLAB from C finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!