Re: [問題] 兩個程式呼叫回傳問題

作者: dirkc (3781615)   2015-05-03 13:16:28
如同版友已經有提到的,程序間通訊 (IPC) 有許多不同的方法。
考量到你提說原本用的是 system() 加上讀寫檔案的作法,
我會建議如果改寫的話,最簡單的作法就是使用 POSIX 規格所提供的
popen()/pclose() 來實作,也就是 unnamed pipe 的方式。
Windows 有提供 _popen() 和 _pclose(),等同於 *nix 下的 popen()/pclose() 函數
舉例,如果寫一支程式要呼叫 dir,並且把執行結果存入 std::string 裡面,
可以如下這樣做:
#include <string> // std::string
#include <iostream> // std::cout
#include <stdio.h> // FILE, feof, fgets, _popen/_pclose
using std::string;
using std::cout;
string exec(char* cmd) {
FILE* pipe = _popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
_pclose(pipe);
return result;
}
int main() {
cout << exec("dir") << '\n';
}
你只需要把 dir 換成你的程式 B,然後再去解析 exec("B") 回傳的字串結果即可。
_popen() 的原理是開啟一個單向的 pipe,透過產生一個新的程序 (fork()) 透過
shell (命令列模式) 去執行所指定的程式 (上面範例中的 char* cmd),並等待程序
執行完畢。流程上類似你直接呼叫 system() 的效果,因為 system() 也是會等待程序
執行完畢。
值得留意的是,_popen() 是開啟程式輸出到 STDOUT 的資料,也就是說一般情況下
用 printf() 或 std::cout 輸出的裝置。如果你的程式 B 是寫到別的裝置,例如
檔案、網路、或者其他 Windows 下的輸出裝置,_popen() 是讀不到的。
如果你輸出到檔案的資料不只是字串這麼單純的話,你也可以把讀取的機制和儲存的
資料結構替換一下,例如換成 fread() 並且將結果存在 std::vector 裡面。
舉例:
#include <vector> // for std::vector
using std::vector;
typedef unsigned char BYTE; // 自己定義你要的位元組型別
int exec2(char* cmd, vector<BYTE> &v) {
FILE* pipe = _popen(cmd, "r");
if (!pipe) return 0; // ERROR
BYTE buffer[128];
size_t n;
while(!feof(pipe)) {
n = fread(buffer, sizeof(BYTE), 128, pipe);
if(n > 0) v.insert(v.end(), buffer, buffer+n);
}
_pclose(pipe);
return 1; // SUCCESS
}
呼叫的地方:
#include <algorithm> // for std::copy
#include <iterator> // for std::ostream_iterator
using std::copy;
using std::ostream_iterator;
int main() {
vector<BYTE> r;
exec2("dir", r);
// 這裡之後可以定義你處理 r 的邏輯
// 底下只是透過 std::copy 簡單將其印出在畫面上
copy(r.begin(), r.end(), ostream_iterator<char>(cout, ""));
}
以上應該是就你描述的情況,改寫程式最短又最簡單的方式了吧,我想。
※ 引述《janice001 (真理)》之銘言:
: 開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
: Windows VC++
: 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
: Nope
: 問題(Question):
: 現在我擁有兩支程式 A 與 B
: A 在程式碼中會使用 System() 的方式使用 B
: 目前是讓 B 使用寫檔的方式,A再去讀取B執行的結果
: 有沒有撇除掉IO 硬碟的方式回傳執行結果??
: 預期的正確結果(Expected Output):
: 可以回傳B程式執行結果
: 錯誤結果(Wrong Output):
: 目前只能使用 寫檔方式溝通
: 補充說明(Supplement):
: 先謝謝各位 Orz
作者: LiloHuang (十年一刻)   2015-05-03 15:52:00
推認真文! popen 聽起來滿適合原po的 :)
作者: janice001 (真理)   2015-05-04 17:17:00
太強惹~~~~

Links booklink

Contact Us: admin [ a t ] ucptt.com