C ++到mex文件:系统命令的输出被抑制

时间:2015-01-13 10:01:52

标签: c++ matlab mex

我编写了一个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

3 个答案:

答案 0 :(得分:1)

您是否尝试过mex-command mexPrintf

但是,在整个mex程序执行之前,输出不会被打印出来。两种解决方法是使用

mexEvalString("disp('Bla')")

 mexPrintf("Bla")
 mexEvalString("drawnow;");

答案 1 :(得分:1)

std::system将启动系统的命令处理器来执行命令。如果您有控制台应用程序,则会将输出打印到当前控制台。这就是您在测试程序中看到它的原因。输出不会传递给调用程序!

在您的情况下,Matlab似乎在后台启动该过程,其中输出被丢弃。尝试打开过程并将其输出读出到程序/ MEX中。

在POSIX中,您可以使用popen(例如参见this answer),在Windows中您可以使用ReadPipe(参见this article

<强>更新
你必须调整我链接的代码。原始代码调用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 );

答案 2 :(得分:0)

查看此问题的答案:Correctly over-loading a stringbuf to replace cout in a MATLAB mex file

您可以替换std::cout中的流缓冲区,以便在MEX文件中的mexPrintf中插入内容时调用std::cout