將程式的輸出傳給TCL

在打包一些現有的程式時(例如 net-snmp, openssl),裡面包含各式各樣的apps。
輸出結果的code散佈在很多地方,而且通常是直接出到stdout,想在tcl得到一樣格式
的結果就要慢慢改,有些複雜一點的輸出格式呼叫一堆function,還有static function,
改起來很麻煩。
以下紀錄一下目前用到的幾種導出結果的方法



#include <stdio.h>
#include <stdlib.h>
#include <tcl.h>

int testA();
int testB();
int testC();

static Tcl_Interp *tclInterp;

#ifdef  __cplusplus
extern  "C"
#endif 
int DLLEXPORT
Outputtest_Init(Tcl_Interp *interp)
{
 if (Tcl_InitStubs(interp, "8.4", 0) == NULL) {
  return TCL_ERROR;
 }
 if (Tcl_PkgProvide(interp, "outputtest", "1.0") == TCL_ERROR) {
  return TCL_ERROR;
 }

 tclInterp = interp;
 Tcl_CreateCommand(interp, "testA" , testA  ,NULL,NULL);
 Tcl_CreateCommand(interp, "testB" , testB  ,NULL,NULL);
 Tcl_CreateCommand(interp, "testC" , testC  ,NULL,NULL);
 
 return TCL_OK;
}

//最簡單的一種,如果輸出結果幫你整理好的只要一個 Tcl_SetResult 把結果導出來就好了
int testA()
{
 printf("This is TestA stdout\n");
 Tcl_SetResult(tclInterp,"This is TestA result",NULL); 
 return 0;
}

//在包netsnmp時最常遇到這種,一個輸出分成好幾段寫,就只好一行一行看,看到有輸出就補一段 Tcl_AppendResult
int testB()
{  
 printf("This is TestB stdout\n");
 Tcl_AppendResult(tclInterp, "This", NULL);
 Tcl_AppendResult(tclInterp, " is", NULL);
 Tcl_AppendResult(tclInterp, " TestB", NULL);
 Tcl_AppendResult(tclInterp, " result", NULL);
 return 0;
}

//在包openssl時,apps太多了,懶的一個一個看,使用取巧的方法
//把stdout導到null (可有可無,沒導的話在cmd下執行這個指令會看到重複的訊息,存到變數一樣只有一個,但是我看不順眼)
//取出值的方法是塞一個buffer去偷資料出來。只要資料不要超過buffer就能一次抓出來,因為我導到NUL,超過buffer資六就會缺
//如果是要跑會出現大量資料的指令可以導到檔案
//(*) close(stdout_save)這句很重要,一開始沒加這行程式跑2000多次就停了,因為OS有開檔案的限制,而 dup 這個 function
//    會開一個新檔

int testC()
{
 int stdout_save;
 char buffer[10240]={};
 fflush(stdout);
 stdout_save = _dup(STDOUT_FILENO);
 freopen("NUL", "a", stdout);
 setvbuf(stdout, buffer, _IOFBF, 10240);
 
 printf("This is TestC");
 
 freopen("NUL", "a", stdout); //redirect stdout to null again
 dup2(stdout_save, STDOUT_FILENO); //restore the previous state of stdout
 close(stdout_save);
 setvbuf(stdout, NULL, _IONBF, 10240); //disable buffer to print to screen instantly 
 Tcl_AppendResult(tclInterp, buffer, NULL);
 return 0;
}






沒有留言:

張貼留言