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

C++ to mex file: output of system command gets suppressed

我写了一个 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] = '[=11=]'; /* 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] = '[=13=]'; /* 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

一些帮助将不胜感激。

此致, 杜尚

你试过mex命令了吗mexPrintf

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

mexEvalString("disp('Bla')")

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

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

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

在POSIX中,您可以使用popen(参见示例this answer), in Windows you can use ReadPipe (cf. 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 );