DLL如何傳遞TBLOBStream到其他程式? |
尚未結案
|
sanhang
一般會員 ![]() ![]() 發表:12 回覆:25 積分:17 註冊:2002-08-31 發送簡訊給我 |
各位大大,小弟有一個不知怎麼實現的需求請教各位高手
今天我想提供一個DLL檔案給另一部門之VC程式開發者
其中有一項功能為透過DLL將Oracle資料庫中的BLOB欄位取出值來
再將此 BlobStream 傳給VC程式 Oracle DB --> Download.dll --> VC-Client.exe 我曉得取得BlobStream的方式
但是從DLL傳給VC程式的這段我卻不知該如何處理
是要用指標傳址的方式來達成嗎?
可以有哪位大大提供一些Sample Code或是文件?
謝謝
|
seaturn99
版主 ![]() ![]() ![]() ![]() 發表:69 回覆:427 積分:214 註冊:2003-08-25 發送簡訊給我 |
|
sanhang
一般會員 ![]() ![]() 發表:12 回覆:25 積分:17 註冊:2002-08-31 發送簡訊給我 |
{ download.dll } function Create_Link: PChar; stdcall; export; function Close_Link: PChar; stdcall; export; procedure Download_Files(TEST_ID, TEST_FILE_NAME : PChar; vProfile : Variant); stdcall; export; { Download 指定的檔案 } procedure Download_Files(TEST_ID, TEST_FILE_NAME : PChar; vProfile : Variant); stdcall; export; var ROWID : string; mstrm : TMemoryStream; fvar : Variant; p : ^TByteArray; begin with DataModule.TempQuery do begin // 先取得ROWID, 以避免Select所有的BLOB欄位 Close; SQL.Clear; SQL.Text := 'SELECT ROWID FROM TEST_BLOB_T ' 'WHERE TEST_ID=' Strpas(TEST_ID) ' AND TEST_FILE_NAME=' QuotedStr(Strpas(TEST_FILE_NAME)); Open; ROWID := FieldByName('ROWID').AsString; // 取得符合條件的BLOB欄位 Close; SQL.Clear; SQL.Text := 'SELECT * FROM TEST_BLOB_T WHERE ROWID=' QuotedStr(ROWID); Open; // 建立 MemoryStream 並儲存 BLOB 欄位資料 mstrm := TMemoryStream.Create; TBLobField(FieldByName('TEST_BLOB')).SaveToStream(mstrm); // 將 MemoryStream 轉換成 Variant fvar := VarArrayCreate([0, mstrm.size-1], VarByte); P := VarArrayLock(fvar); mstrm.Seek(0,soBeginning); mstrm.ReadBuffer(p^, mstrm.size); VarArrayUnLock(fvar); mstrm.Free; vProfile := fvar; end; end; { 測試程式 Test-Client.exe } procedure Download_Files(TEST_ID, TEST_FILE_NAME : PChar; vProfile : Variant); stdcall; external 'download.dll'; procedure TForm1.btn7Click(Sender: TObject); var p:^TByteArray; pos :Int64; mstrm : TMemoryStream; vfile : Variant; sfilename : string; begin // 呼叫 Download_file 並回傳 vfile Download_files(PChar(edtTEST_ID.Text), PChar(Trim(edtFileName.Text)), vfile); // 建立 MemoryStream mstrm := TMemoryStream.Create; // 將 Variant 轉換成 MemoryStream P := VarArrayLock(vfile); pos := mstrm.Seek(0, soBeginning); mstrm.WriteBuffer(p^,VarArrayHighBound(vfile,1) 1); mstrm.Seek(pos,soBeginning); VarArrayUnLock(vfile); // 存成實體檔案 mstrm.SaveToFile('C:\' Trim(edtFileName.Text)); mstrm.Free; end;以上是部份程式,轉換的部份是參考另一篇文章的作法 可是在測試的時候卻出現Access Violation 出現too mamy consecutive exceptions 請教各位到底是哪邊做錯了呢? |
sanhang
一般會員 ![]() ![]() 發表:12 回覆:25 積分:17 註冊:2002-08-31 發送簡訊給我 |
{ download.dll } function Create_Link: PChar; stdcall; export; function Close_Link: PChar; stdcall; export; procedure Download_Files(TEST_ID, TEST_FILE_NAME : PChar; vProfile : Variant); stdcall; export; { Download 指定的檔案 } procedure Download_Files(TEST_ID, TEST_FILE_NAME : PChar; vProfile : Variant); stdcall; export; var ROWID : string; mstrm : TMemoryStream; fvar : Variant; p : ^TByteArray; begin with DataModule.TempQuery do begin // 先取得ROWID, 以避免Select所有的BLOB欄位 Close; SQL.Clear; SQL.Text := 'SELECT ROWID FROM TEST_BLOB_T ' 'WHERE TEST_ID=' Strpas(TEST_ID) ' AND TEST_FILE_NAME=' QuotedStr(Strpas(TEST_FILE_NAME)); Open; ROWID := FieldByName('ROWID').AsString; // 取得符合條件的BLOB欄位 Close; SQL.Clear; SQL.Text := 'SELECT * FROM TEST_BLOB_T WHERE ROWID=' QuotedStr(ROWID); Open; // 建立 MemoryStream 並儲存 BLOB 欄位資料 mstrm := TMemoryStream.Create; TBLobField(FieldByName('TEST_BLOB')).SaveToStream(mstrm); // 將 MemoryStream 轉換成 Variant fvar := VarArrayCreate([0, mstrm.size-1], VarByte); P := VarArrayLock(fvar); mstrm.Seek(0,soBeginning); mstrm.ReadBuffer(p^, mstrm.size); VarArrayUnLock(fvar); mstrm.Free; vProfile := fvar; end; end; { 測試程式 Test-Client.exe } procedure Download_Files(TEST_ID, TEST_FILE_NAME : PChar; vProfile : Variant); stdcall; external 'download.dll'; procedure TForm1.btn7Click(Sender: TObject); var p:^TByteArray; pos :Int64; mstrm : TMemoryStream; vfile : Variant; sfilename : string; begin // 呼叫 Download_file 並回傳 vfile Download_files(PChar(edtTEST_ID.Text), PChar(Trim(edtFileName.Text)), vfile); // 建立 MemoryStream mstrm := TMemoryStream.Create; // 將 Variant 轉換成 MemoryStream P := VarArrayLock(vfile); pos := mstrm.Seek(0, soBeginning); mstrm.WriteBuffer(p^,VarArrayHighBound(vfile,1) 1); mstrm.Seek(pos,soBeginning); VarArrayUnLock(vfile); // 存成實體檔案 mstrm.SaveToFile('C:\' Trim(edtFileName.Text)); mstrm.Free; end;以上是部份程式,轉換的部份是參考另一篇文章的作法 可是在測試的時候卻出現Access Violation 出現too mamy consecutive exceptions 請教各位到底是哪邊做錯了呢? |
seaturn99
版主 ![]() ![]() ![]() ![]() 發表:69 回覆:427 積分:214 註冊:2003-08-25 發送簡訊給我 |
sanhang 您好 : 看起來邏輯好像沒有錯,建議您先 copy StreamToVariant 與 VariantToStream 兩個函數當作 black box 使用,這兩個函數我有實際使用過,沒有問題 .. 另外,建議您可以把 error 視窗貼出來參考...
您可以利用 step trace 或 break point 逐步追,可以縮小範圍 (先不要編成 dll,改成 Unit 比較好 trace)... 一個不一定準的直覺 : 會不會 TEST_BLOB Field 傳回 NULL ?? ----
我只會兩件事,這也不會,那也不會 眼見不一定為真
----
|
sanhang
一般會員 ![]() ![]() 發表:12 回覆:25 積分:17 註冊:2002-08-31 發送簡訊給我 |
|
seaturn99
版主 ![]() ![]() ![]() ![]() 發表:69 回覆:427 積分:214 註冊:2003-08-25 發送簡訊給我 |
sanhang 您好 : 這幾天較忙,也再實驗了 speedup 大大的兩個 function ,證實功能正常...
所以一直百思不解 .. 今天靜下心來看你原來的 Source Code :
procedure Download_Files(TEST_ID, TEST_FILE_NAME : PChar;var vProfile : Variant); stdcall; export; 加上 var 關鍵字就可以正確執行了 ... 建議還是 Copy Speedup 大大的 function 把他當作黑盒子使用,這樣可以提高 Code Reuse ,也可以讓您的程式碼簡潔易 debug .. 直覺,做成 dll 應該要注意一些直接傳 Address 的問題.. ----
我只會兩件事,這也不會,那也不會 眼見不一定為真
---- 發表人 - SouthWind 於 2004/11/30 16:41:49
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |