C ++ в mex файл: вывод системной команды подавляется

0

Я написал код C++, который я конвертирую в файл mex, чтобы я мог работать из Matlab. В моем исходном коде C++ отображается вывод некоторой функции, объявленной в сторонней библиотеке. Однако, когда я конвертирую его в файл mex, выход кажется подавленным.

ПРИМЕЧАНИЕ: вывод следующей команды будет подавлен

 int systemRet = std::system("./genb_test");

Исходный код:

 #include <stdio.h>  /* defines FILENAME_MAX */
 #include <cstdlib>

 #include <iostream>
 #ifdef _MSC_VER
    #include "direct.h" 
    #define GetCurrentDir _getcwd // window ??
 #else
    #include "unistd.h"
        #define GetCurrentDir getcwd
 #endif


int main()
{
  const char *ParentFolder = "/home/dkumar/libtsnnls-2.3.3/tsnnls/";

  int res3 = chdir(ParentFolder);
  if (res3  == -1){
    // The system method failed
    std::cout<< "the chdir method has failed \n"; 
  }    

  char cCurrentPath[FILENAME_MAX];
  if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
  {
      printf("Could not find current directory " );
      // return errno;
  }
  cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */
  printf ("The current working directory is %s", cCurrentPath);
  printf ("\n");

  printf("Now running genb test " );
  int systemRet = std::system("./genb_test");
  if(systemRet == -1){
    // The system method failed
  }else{
    printf("System command execuated successfully " );
  }

return 0;
}

Выход из исходного кода:

The current working directory is /home/dkumar/libtsnnls-2.3.3/tsnnls
genb_tests

Creating 100 random test 121 x 89 problems using 
the genb algorithm of PJV. Each problem will be given 
to the tsnnls method, and the error printed below.
We require an error less than 1e-8 to pass the test.

#    M    N     Error         (PJV error)   (Spiv error)   Result 
----------------------------------------------------------------- 
  1  121  89    1.375271e-15  1.375271e-15  0.000000e+00  pass
  2  121  89    1.953126e-15  1.953126e-15  0.000000e+00  pass
  3  121  89    4.272569e-15  4.272569e-15  0.000000e+00  pass
  4  121  89    1.440234e-15  1.440234e-15  0.000000e+00  pass
  5  121  89    2.392671e-15  2.392671e-15  0.000000e+00  pass
 .......
 ....... 

 98  121  89    4.696796e-15  4.696796e-15  0.000000e+00  pass
 99  121  89    1.820247e-15  1.820247e-15  0.000000e+00  pass
100  121  89    1.520109e-15  1.520109e-15  0.000000e+00  pass

100 (of 100) tests passed.
Now running genb test System command execuated successfully

Перевод исходного кода в файл mex: различные входные и выходные данные (LHS) оставлены как есть, так как я начну использовать это в ближайшее время.

#include <matrix.h> // mex
#include <mex.h>    // mex

#include <iostream>  // Basic I/O
using namespace std; // Basic I/O


/* Definitions to keep compatibility with earlier versions of ML */
#ifndef MWSIZE_MAX
typedef int mwSize;
typedef int mwIndex;
typedef int mwSignedIndex;

#if (defined(_LP64) || defined(_WIN64)) && !defined(MX_COMPAT_32)
/* Currently 2^48 based on hardware limitations */
# define MWSIZE_MAX    281474976710655UL
# define MWINDEX_MAX   281474976710655UL
# define MWSINDEX_MAX  281474976710655L
# define MWSINDEX_MIN -281474976710655L
#else
# define MWSIZE_MAX    2147483647UL
# define MWINDEX_MAX   2147483647UL
# define MWSINDEX_MAX  2147483647L
# define MWSINDEX_MIN -2147483647L
#endif
#define MWSIZE_MIN    0UL
#define MWINDEX_MIN   0UL
#endif

// 'Hello World!' program 
 #include <stdio.h>  /* defines FILENAME_MAX */
 #include <cstdlib>

 #include <iostream>
 #ifdef _MSC_VER
    #include "direct.h" 
    #define GetCurrentDir _getcwd // window ??
 #else
    #include "unistd.h"
        #define GetCurrentDir getcwd
 #endif


void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{

  //const char *ParentFolder = "/home/dkumar/All_Matlab_Codes_DKU/";
  const char *ParentFolder = "/home/dkumar/libtsnnls-2.3.3/tsnnls/";


//declare variables
    mxArray *a_in_m, *b_in_m, *c_out_m, *d_out_m;
    const mwSize *dims;
    double *a, *b, *c, *d;
    int dimx, dimy, numdims;
    int i,j;

//associate inputs
    a_in_m = mxDuplicateArray(prhs[0]);
    b_in_m = mxDuplicateArray(prhs[1]);

//figure out dimensions
    dims = mxGetDimensions(prhs[0]);
    numdims = mxGetNumberOfDimensions(prhs[0]);
    dimy = (int)dims[0]; dimx = (int)dims[1];

//associate outputs
    c_out_m = plhs[0] = mxCreateDoubleMatrix(dimy,dimx,mxREAL);
    d_out_m = plhs[1] = mxCreateDoubleMatrix(dimy,dimx,mxREAL);

//associate pointers
    a = mxGetPr(a_in_m);
    b = mxGetPr(b_in_m);
    c = mxGetPr(c_out_m);
    d = mxGetPr(d_out_m);


  std::cout<< "Trying to change the directory "<< "\n";

  // COPIED FROM ORIGINAL C++ 
  int res3 = chdir(ParentFolder);
  if (res3  == -1){
    // The system method failed
    std::cout<< "the chdir method has failed \n"; 
  }

  char cCurrentPath[FILENAME_MAX];
  if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
  {
      printf("Could not find current directory " );
      // return errno;
  }
  cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */
  printf ("The current working directory is %s", cCurrentPath);
  printf ("\n");

  printf("Now running genb test " );
  int systemRet = std::system("./genb_test");
  if(systemRet == -1){
    // The system method failed
  }else{
    printf("System command execuated successfully " );
  }

   // ADDED THIS PART at the suggestion of king_nak
   //Capturing the output terminal
    FILE * f = popen( "ls -al", "r" );
    if ( f == 0 ) {
        fprintf( stderr, "Could not execute\n" );
        return;
    }
    const int BUFSIZE = 1000;
    char buf[ BUFSIZE ];
    while( fgets( buf, BUFSIZE,  f ) ) {
        fprintf( stdout, "%s", buf  );
    }
    pclose( f );

    return;
}

Выход:

>> [c d]=test_snnls_mex(a,b)
Trying to change the directory 
The current working directory is /home/dkumar/libtsnnls-2.3.3/tsnnls
Now running genb test 
c =

     6     7     8
     9    10    11
    12    13    14


d =

     1     4     9
    16    25    36
    49    64    81

Некоторая помощь будет оценена по достоинству.

С уважением, Dushyant

Теги:
mex

3 ответа

1
Лучший ответ

std::system запустит командный процессор системы для выполнения команды. Если у вас есть консольное приложение, это приведет к выводу вывода на текущую консоль. Вот почему вы видите это в своей тестовой программе. Выход не передается вызывающей программе!

В вашем случае Matlab, похоже, запускает процесс в фоновом режиме, где выход отбрасывается. Попробуйте вместо этого открыть процесс и прочесть его вывод в вашей программе /MEX.

В POSIX вы можете использовать popen (см. например, этот ответ), в Windows вы можете использовать ReadPipe (см. Эту статью)

ОБНОВИТЬ
Вы должны настроить код, с которым я связан. Исходный код вызывает ls -al и выводит его вывод на экран. Вы должны вызвать свой процесс genb_test !

Используйте этот код, чтобы получить результат в matlab вместо вашего std::system вызова:

FILE * f = popen( "genb_test", "r" );  // <- call genb_test
if ( f == 0 ) {
    fprintf( stderr, "Could not execute\n" );
    return;
}
const int BUFSIZE = 1000;
char buf[ BUFSIZE ];
while( fgets( buf, BUFSIZE,  f ) ) {
    mexPrintf(buf); // <- use mexPrintf to print to matlab
}
pclose( f );
  • 0
    Благодарю. Я мог видеть вывод в терминале, откуда я начал Matlab. Я также попытался использовать popen (см. Мой измененный код), и он также, похоже, отправляет вывод на терминал ИЛИ, возможно, я не использую его должным образом. Тем не менее, я хотел бы захватить вывод команды с помощью системы: c = run_some_test (input ...); Другими словами, я хотел бы, чтобы значение c было доступно в mex файле. Пожалуйста помоги.
  • 0
    Я расширил ответ с примером. Вы должны назвать свой процесс, а не ls -al !
1

Вы пробовали mex-команду mexPrintf?

Однако выход не будет напечатан до того, как будет запущена вся mex-программа. Для этого нужно использовать два подхода: использовать

mexEvalString("disp('Bla')")

или

 mexPrintf("Bla")
 mexEvalString("drawnow;");
  • 0
    Вызов mexEvalString ("./ genb_test") или mexEvalString ("system (" ./ genb_test ")") вызывает ошибку. Не могли бы вы уточнить, пожалуйста.
  • 0
    Также я понимаю, что mex-файл должен точно повторять то, что я делал в своем коде C ++.
Показать ещё 2 комментария
0

Посмотрите на ответы на этот вопрос: Правильно перегрузите stringbuf для замены cout в mex файле MATLAB

Вы можете заменить буфер потока внутри std::cout так, чтобы mexPrintf вызывается всякий раз, когда вы вставляете что-то в std::cout в ваш MEX файл.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню