【问题标题】:C++ to mex file: output of system command gets suppressedC++ 到 mex 文件:系统命令的输出被抑制
【发布时间】:2016-12-22 13:55:39
【问题描述】:

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

我们将不胜感激。

问候, 杜夏特

【问题讨论】:

    标签: c++ matlab mex


    【解决方案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 );
    

    【讨论】:

    • 谢谢。我可以在我启动 matlab 的终端上看到输出。我也尝试使用 popen (请参阅我修改后的代码),它似乎也正在向终端发送输出,或者,我可能没有正确使用。但是,我想使用系统捕获命令的输出: c = run_some_test(inputs...);换句话说,我希望 c 的值在 mex 文件中可用。请帮忙。
    • 我用一个例子扩展了答案。您必须调用您的流程,而不是 ls -al
    【解决方案2】:

    你试过 mex-command mexPrintf 吗?

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

    mexEvalString("disp('Bla')")
    

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

    【讨论】:

    • 调用 mexEvalString("./genb_test") 或 mexEvalString("system("./genb_test")") 给我错误。能否请您详细说明。
    • 我的理解是 mex 文件应该完全复制我在 C++ 代码中所做的工作。
    • 试试mexEvalString("disp('...')")mexEvalString 在你的 mex 程序中调用一个 matlab 函数 - 而“./genb_test”不是一个 matlab 函数。
    • 感谢您的澄清。 ./genb_test 是 gcc 可执行文件。这意味着您的解决方案对这种情况无效。
    猜你喜欢
    • 2017-12-21
    • 2011-05-03
    • 2019-02-16
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 2016-06-03
    • 1970-01-01
    • 2010-10-13
    相关资源
    最近更新 更多