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