全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1646
推到 Plurk!
推到 Facebook!

DLL如何傳遞TBLOBStream到其他程式?

尚未結案
sanhang
一般會員


發表:12
回覆:25
積分:17
註冊:2002-08-31

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-11-25 00:55:47 IP:211.74.xxx.xxx 未訂閱
各位大大,小弟有一個不知怎麼實現的需求請教各位高手 今天我想提供一個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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-11-25 01:00:16 IP:211.76.xxx.xxx 未訂閱
sanhang 您好 : 您可以利用 Variant 傳遞,請參考 speedup 大大的文章 : http://delphi.ktop.com.tw/topic.php?TOPIC_ID=52498 PS. 雖然是 Delphi Code ,不過應該很容易翻成 BCB .... ---- 我只會兩件事,這也不會,那也不會 眼見不一定為真 ----
sanhang
一般會員


發表:12
回覆:25
積分:17
註冊:2002-08-31

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-11-25 17:12:01 IP:61.222.xxx.xxx 未訂閱
 
{ 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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-11-25 17:17:45 IP:61.222.xxx.xxx 未訂閱
 
{ 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

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-11-25 19:58:44 IP:220.130.xxx.xxx 未訂閱
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

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-11-26 12:19:49 IP:61.222.xxx.xxx 未訂閱
Southwind 你好 :  很感謝您的熱心回應 我按照你的指示做, 先不用DLL的架構來做測試  可是我的測試程式會在 VariantToStream 的  P:=VarArrayLock(Source);  出現EVariantInvalidArgError類別的錯誤"Invalid argument"     我確定BLOBField有取出資料, 希望Southwind版主或各位高手再指點我一下
seaturn99
版主


發表:69
回覆:427
積分:214
註冊:2003-08-25

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-11-30 15:28:14 IP:220.130.xxx.xxx 未訂閱
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
系統時間:2024-07-06 17:37:12
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!