フィルターのクリア

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

1 回表示 (過去 30 日間)
shome
shome 2015 年 11 月 18 日
編集済み: James Tursa 2015 年 11 月 18 日
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 Center および File ExchangeCall C++ from MATLAB についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by