2012-12-06 78 views
2

我有一個放大圖像的Tcl程序。如何將C++ unsigned char []傳遞給Tcl bytearray?

proc ShowWindow {wtitle zfactor imgdata} { 

puts stdout "Now in the Tcl procedure ShowWindow!"; 

image create photo idata -data $imgdata; # create a photo image from the input data 
image create photo the_window;  # final window 

the_window copy idata -zoom $zfactor $zfactor; # copy the original and magnify 

wm title . $wtitle;   # window title 
wm resizable . false false;  # no resizing in both x and y directions 

catch {destroy .dwindow};  # since this procedure will be called multiple times 
       # we need to suppress the 'window name "dwindow" already exists in parent' message 

label .dwindow -image the_window; # create a label to display the image 
pack .dwindow;   # display the image 

} 

我想從C++中調用這個Tcl過程。

我認爲「imgdata」是一個ByteArray。它是否正確?

相關代碼片段如下所示:

// ...Tcl/Tk initialization omitted... 

unsigned char *img; // PPM image data 
int num_bytes;  // PPM image file size 

// ...routines to initialize img and num_bytes omitted... 

Tcl_Obj *tcl_raw; 

// transfer the PPM image data into Tcl_Obj 

if (!(tcl_raw = Tcl_NewByteArrayObj(img, num_bytes))) { 
    cerr << "Tcl_NewByteArrayObj() failed!" << endl; 
    cerr << "Exiting..." << endl; 
    return 1; 
} else { 
    cerr << "Tcl_NewByteArrayObj() succeeded!" << endl; 
} 

Tcl_IncrRefCount(tcl_raw); // is this really necessary? 

// set the Tcl variable "imgdata" to the Tcl_Obj 

if (Tcl_SetVar2Ex(tcl_interpreter, "imgdata", "", tcl_raw, TCL_LEAVE_ERR_MSG) == NULL) { 
    cerr << "Tcl_SetVar2Ex() failed!" << endl; 
    cerr << "Exiting..." << endl; 
    return 1; 
} else { 
    cerr << "Tcl_SetVar2Ex() succeeded!" << endl; 
} 

// execute the Tcl procedure 

if (Tcl_Eval(tcl_interpreter, "ShowWindow TheImage 8 $imgdata") != TCL_OK) { 
    cerr << "Tcl_Eval() failed!" << endl; 
    cerr << "Tcl_GetStringResult() = " << Tcl_GetStringResult(tcl_interpreter) << endl; 
    cerr << "Exiting..." << endl; 
    return 1; 
} else { 
    cerr << "Tcl_Eval() succeeded!" << endl; 
} 

程序在Tcl_Eval失敗()。程序輸出是:

... 
Tcl_NewByteArrayObj() succeeded! 
Tcl_SetVar2Ex() succeeded! 
Tcl_Eval() failed! 
Tcl_GetStringResult() = can't read "imgdata": variable is array 
Exiting... 

這樣做的建議方法是什麼?

回答

1

可以使用Tcl_ByteArraySetLength或Tcl_GetByteArrayFromObj將Tcl ByteArrayObj類型視爲緩衝區,這兩者都可以訪問Tcl對象的數據部分。

Tcl_Obj *dataObj = Tcl_NewObj(); 
char *dataPtr = Tcl_SetByteArrayLength(dataObj, 1024); 

現在您可以使用dataPtr來設置對象中的字節。 Tcl_SetByteArrayLength函數將使這個對象成爲一個ByteArray類型。

然而,你可能也想看看imgscale我使用拉伸Tk的圖像,這使用不同的插補方式如:

image create photo thumbnail 
::imgscale::bilinear $myphoto 64 64 thumbnail 1.0 

來縮減一些照片轉換成縮略圖。

+0

感謝@patthoyts的快速反應!如果我理解正確,Tcl_NewByteArrayObj(bytes,num_bytes)將創建一個新的ByteArray對象,並「將該對象的內部表示設置爲由字節給出的字節數組的副本」。如果是這樣,爲什麼使用Tcl_NewObj()和你概述的方法?請注意,我並不是試圖從C++創建一個新的Tcl命令,而是試圖從C++調用一個Tcl過程。再次感謝! – user1882115

+1

@user Tcl和C++對於對象是什麼有不同的理念;不要費力嘗試複製術語。 'Tcl_NewObj'分配一個新的原始值(最初是一個空值),'Tcl_SetByteArrayLength'配置一個現有值爲一個特定長度的字節數組,並且方便地返回一個指向這些字節的指針。然後,您可以按照您認爲合適的方式填充該數組,然後將發送「Tcl_Obj」值將其保存到合適的例程中。 –

+0

謝謝你的提示/提示!發佈代碼中唯一的錯誤是:'Tcl_SetVar2Ex(tcl_interpreter,「imgdata」,「」,tcl_raw,TCL_LEAVE_ERR_MSG)'。空雙引號是* not * NULL,因此Tcl將「imgdata」解釋爲數組而不是二進制字符串。 「正確的」調用應該是:'Tcl_SetVar2Ex(tcl_interpreter,「imgdata」,NULL,tcl_raw,TCL_LEAVE_ERR_MSG)'表示一個標量變量。總結:(1)使用C ByteArrayObj API(2)使用Tcl_SetVar2Ex()創建並設置Tcl變量 – user1882115

相關問題