can we use matlab engine from a inside a function in C++

1 次查看(过去 30 天)
I compiled a C++ program to sort double values(matlab does the sorting). it works fine. however when i move the code related to matlab computation to a function, it gives erroneous results.
following is the code with both the formats in a single file. when i execute matlab functions from main it works, when i execute the matlab part from a function(call_matlab_processing) it gives random results.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "engine.h"
#include <iostream>
#include <vector>
#define BUFSIZE 256
int call_matlab_processing(double double_array[], int size_double_array,double * sorted, double * indices_cpp)
{
for (int i=0;i<size_double_array;i++)
{
std::cout << "double array at "<< i << " "<< double_array[i]<<std::endl;
}
Engine *ep;
mxArray *T = NULL, *result = NULL, *indices=NULL;
/*
* 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 1;
}
T = mxCreateDoubleMatrix(1,size_double_array, mxREAL);
memcpy((void *)mxGetPr(T), (void *)double_array, sizeof(double_array));
/** Place the variable T into the MATLAB workspace */
engPutVariable(ep, "T", T);
engEvalString(ep, "[D I] = sort(T,'descend')");
engEvalString(ep, "dlmwrite('myFile.txt',D)");
result = engGetVariable(ep,"D");
indices = engGetVariable(ep,"I");
sorted=(double *)mxGetData(result);
indices_cpp=(double *)mxGetData(indices);
/* for (int i=0;i<10;i++)
{
std::cout << "sorted= " <<*sorted << " indices= " << *indices_cpp <<std::endl;
sorted++;
indices_cpp++;
}*/
mxDestroyArray(T);
mxDestroyArray(result);
mxDestroyArray(indices);
engEvalString(ep, "close;");
engClose(ep);
return 0;
}
int main()
{
int size_double_array=10;
double double_array[10]={ 0, 5, 2, 7, 3, 9, 1, 6, 8, 4 };
double * sorted;
double * indices_cpp;
Engine *ep;
mxArray *T = NULL, *result = NULL, *indices=NULL;
if (!(ep = engOpen(""))) {
fprintf(stderr, "\nCan't start MATLAB engine\n");
return 1;
}
T = mxCreateDoubleMatrix(1,size_double_array, mxREAL);
memcpy((void *)mxGetPr(T), (void *)double_array, sizeof(double_array));
engPutVariable(ep, "T", T);
engEvalString(ep, "[D I] = sort(T,'descend')");
engEvalString(ep, "dlmwrite('myFile.txt',D)");
result = engGetVariable(ep,"D");
indices = engGetVariable(ep,"I");
sorted=(double *)mxGetData(result);
indices_cpp=(double *)mxGetData(indices);
mxDestroyArray(T);
mxDestroyArray(result);
mxDestroyArray(indices);
engEvalString(ep, "close;");
engClose(ep);
// int result=call_matlab_processing(double_array,10,sorted,indices_cpp);
for (int i=0;i<10;i++)
{
std::cout << "sorted= " <<*sorted << " indices= " << *indices_cpp <<std::endl;
sorted++;
indices_cpp++;
}
std::cout << "Done"<< std::endl;
return EXIT_SUCCESS;
}
  2 个评论
Abdelmoumen Bacetti
Abdelmoumen Bacetti 2015-11-18
Please, use "{}code" to format your code.
I'm sure if you refer to one of Matlab's examples, you will find a clue.
shome
shome 2015-11-18
编辑:shome 2015-11-18
i have not come across that format. can you kindly refer to an example. i checked imread.m. icould find {} but nothing like {}code.
are you speaking about code formating wrt indentation
i am unable to understand. plz help. i can make my code simpler if my code looks ugly.but can you please be specific as to why the code in the function is giving wrong results.

请先登录,再进行评论。

采纳的回答

James Tursa
James Tursa 2015-11-18
编辑:James Tursa 2015-11-18
You have a fundamental flaw in your code. You free the memory behind the pointers that you use downstream in your code. E.g.,
result = engGetVariable(ep,"D"); // <-- Creates the mxArray result, including the data area
indices = engGetVariable(ep,"I"); // <-- Creates the mxArray indices, including the data area
sorted=(double *)mxGetData(result); // <-- Gets pointer to data area of result
indices_cpp=(double *)mxGetData(indices); // <-- Gets pointer to data area of indices
mxDestroyArray(T);
mxDestroyArray(result); // <-- Wipes out result, *and* the memory behind sorted
mxDestroyArray(indices); // <-- Wipes out indices, *and* the memory behind indices_cpp
// So at this point in the code, both of the pointers sorted and indices_cpp are *invalid*
engEvalString(ep, "close;");
engClose(ep);
// Code downstream of here uses *invalid* pointers. Anything can happen.
// Could get lucky good results, or random bad results, or even a program bomb.
// int result=call_matlab_processing(double_array,10,sorted,indices_cpp);
for (int i=0;i<10;i++)
{
std::cout << "sorted= " <<*sorted << " indices= " << *indices_cpp <<std::endl;
sorted++;
indices_cpp++;
}
You need to delay executing these two lines until after you are done using their data areas:
mxDestroyArray(result);
mxDestroyArray(indices);
  3 个评论
James Tursa
James Tursa 2015-11-18
Can you post the current code you are using that gets the wrong result so I can look at it? To answer your question directly, the answer is YES you can call the MATLAB Engine from inside a function. (Strictly speaking, main is a function also)
James Tursa
James Tursa 2015-11-18
编辑:James Tursa 2015-11-18
Oh, I just noticed these lines:
int call_matlab_processing(double double_array[], int size_double_array,double * sorted, double * indices_cpp)
{
:
memcpy((void *)mxGetPr(T), (void *)double_array, sizeof(double_array));
The first argument of the function call_matlab_processing is the variable double_array. It turns out that this variable is of type "pointer to double" (i.e., double * ). I know it looks like you have declared it as an array, but that syntax is misleading. When used in a function argument, the notation
double variable_name[]
is equivalent to the notation
double *variable_name
In fact, even if you had use an explicit size it would have made no difference to the compiler. I.e., this notation in a function argument
double variable_name[10]
is also equivalent to the notation
double *variable_name
That is, the compiler sees that argument as a pointer, not as an array (you can't pass whole arrays in C/C++ function arguments this way). So downstream in your code when you use sizeof(double_array), it is equivalent to doing sizeof(double * ). The result will be either 4 (on 32-bit) or 8 (on 64-bit). So you are definitely not copying all of the elements in that memcpy call. You need to do this instead:
memcpy((void *)mxGetPr(T), (void *)double_array, size_double_array*sizeof(double));
Note that this is entirely different from what you have in main:
double double_array[10]={ 0, 5, 2, 7, 3, 9, 1, 6, 8, 4 };
:
memcpy((void *)mxGetPr(T), (void *)double_array, sizeof(double_array));
Here in main double_array is in fact an array, so sizeof(double_array) will be the full memory for this array, i.e. 10*8 = 80 bytes.
Also, FYI you don't really need the (void *) casts since converting pointers to/from void * is something the C/C++ compiler will automatically do for you.

请先登录,再进行评论。

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Call C++ from MATLAB 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by