研究這的目的,是要在Visual C++視窗模式下呼叫gnuplot
也順便解決了呼叫新版gnuplot會出現的問題:
Timeout: gnuplot is not ready
原本只會用C的popen()來呼叫gnuplot,或用Visual C++的_popen()。
這種方法在console(控制台,黑黑的視窗)模式下是可行的。
但在VC++的視窗模式下,是無法使用_popen()的。
因為popen()是Unix系統的pipe function,Windows系統雖有模擬,但使用上有些限制( ex. 視窗程式不能用 )
因為在視窗程式不能用_popen(),只好用在console模式下寫另一只程式Callgnuplot
然後再用視窗程式呼叫Callgnuplot讀檔畫圖
system( "Callgnuplot.exe" )
但這種方式會出現黑色console視窗,有礙觀瞻
就算Callgnuplot裡加上隱藏視窗,還是會閃一下黑色視窗
Using popen():
→指令傳遞方向
My Program ( console )
↓
↓ popen() function
↓
pgnuplot.exe
↓
↓ pipe function of Windows
↓
wgnuplot.exe ( GUI )
此方法適用於:
舊版gnuplot
compiler: mingw32-gcc
compiler: VC++ console 模式 (popen要改成_popen)
無法用於 VC++ 視窗模式
系統: Windows XP gnuplot版本: Version 4.4 patchlevel 0-rc1 (gp44rc1win32)
/*******************************************************************/
#include <stdio.h>
int main( void )
{
FILE *command;
//command = popen( "gnuplot", "w" ); // XP可用,Vista不行
command = popen( "pgnuplot", "w" ); // XP Vista 皆可
fprintf( command, "plot x**2\n" );
fflush( command ); // 清空pipe緩衝區裡的指令,把指令傳到 pgnuplot,此時圖才會畫出來
//為了慢慢欣賞畫出的圖,這裡要放暫停的指令
pclose( command ); // 清除pipe緩衝區裡的指令,此時gnuplot就被關掉了
return 0;
}
/*******************************************************************/
以上程式修改自:
Appendix B. Call gnuplot from C program
用popen呼叫新版gnuplot( Version 4.4 patchlevel 3 )( gp443win32 )
每次都會出現Timeout: gnuplot is not ready,且畫不出圖
我曾試著在popen之後加上Sleep,還是失敗
後來找到pgnuplot的原始碼,從中找到用Windows的pipe function呼叫gnuplot的方式
於是視窗程式也可以直接呼叫gnuplot!!!
順便也解決了呼叫新版gnuplot會出現的問題:
Timeout: gnuplot is not ready
Timeout: gnuplot is not ready
Using pipe function of Windows:
→指令傳遞方向
My Program ( console or 視窗 )
↓
↓ pipe function of Windows
↓
wgnuplot.exe ( GUI )
/*******************************************************************/
#include <stdio.h>
#include <windows.h>
#define PROGNAME "wgnuplot.exe"
#define TEXTCLASS "wgnuplot_text"
/* GLOBAL Variables */
HWND hwndParent = NULL;
HWND hwndText = NULL;
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
/* CRS: Callback for the EnumThreadWindows function */
BOOL CALLBACK
cbGetTextWindow(HWND hwnd, LPARAM lParam)
{
/* save the value of the parent window */
hwndParent = hwnd;
/* check to see if it has a child text window */
hwndText = FindWindowEx(hwnd, NULL, TEXTCLASS, NULL);
/* if the text window was found, stop looking */
return (hwndText == NULL);
}
/* sends a string to the specified window */
/* CRS: made this into a function call */
void
PostString(HWND hwnd, char *pc)
{
while(*pc) {
PostMessage(hwnd, WM_CHAR, (unsigned char) *pc, 1L);
/* CRS: should add a check of return code on PostMessage. If 0, the
message que was full and the message wasn't posted. */
pc++;
}
}
int
main ()
{
char psGnuplotCommandLine[MAX_PATH] = PROGNAME;
BOOL bSuccess;
/* CRS: initialize the STARTUPINFO and call CreateProcess(). */
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.lpReserved = NULL;
siStartInfo.lpReserved2 = NULL;
siStartInfo.cbReserved2 = 0;
siStartInfo.lpDesktop = NULL;
siStartInfo.dwFlags = STARTF_USESHOWWINDOW;
siStartInfo.wShowWindow = SW_SHOWMINIMIZED;
//如果不加下面這兩行, 會Error:998
ZeroMemory(&piProcInfo, sizeof(piProcInfo) );
ZeroMemory(&siStartInfo, sizeof(siStartInfo) );
bSuccess = CreateProcess(
NULL, /* pointer to name of executable module */
psGnuplotCommandLine, /* pointer to command line string */
NULL, /* pointer to process security attributes */
NULL, /* pointer to thread security attributes */
FALSE, /* handle inheritance flag */
0, /* creation flags */
NULL, /* pointer to new environment block */
NULL, /* pointer to current directory name */
&siStartInfo, /* pointer to STARTUPINFO */
&piProcInfo /* pointer to PROCESS_INFORMATION */
);
/* if CreateProcess() failed, print a warning and exit. */
if (! bSuccess) {
fprintf(stderr,"ERROR %u: Couldn't execute: \"%s\"\n",
GetLastError(), psGnuplotCommandLine);
exit(EXIT_FAILURE);
}
Sleep(1000); // 這行是我加的,不加的話,新版的gnuplot會失敗
if (WaitForInputIdle(piProcInfo.hProcess, 1000)) {
fprintf(stderr, "Timeout: gnuplot is not ready\n");
exit(EXIT_FAILURE);
}
/* CRS: get the HWND of the parent window and text windows */
EnumThreadWindows(piProcInfo.dwThreadId, cbGetTextWindow, 0);
/* CRS: free the process and thread handles */
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
//下面3行是我隨意寫的,你可以改成你想要的指令傳給gnuplot
PostString(hwndText, "plot x**2\n");
Sleep(10000);
PostString(hwndText, "\nexit\n");
return EXIT_SUCCESS;
}
/*******************************************************************/
以上程式修改自:
沒有留言:
張貼留言