cannot assign a TBitmap to a TJpegImage |
答題得分者是:jow
|
t111
一般會員 發表:3 回覆:5 積分:1 註冊:2006-10-30 發送簡訊給我 |
Uses Sharemem, Classes, SysUtils, Dialogs, Forms, Windows, Controls, inifiles,
ComObj, StdCtrls, DateUtils, Jpeg, Graphics; Function BMPtoJPE(aBMP: TBitmap): TJPEGImage; Var JPG: TJPEGImage; begin JPG:= TJPEGImage.Create; JPG.Assign(aBMP); Result := JPG; end; 以上代碼在程序中直接運行正確, 但寫成DLL後, 出現'Cannot assgin a TBitmap to a TJPEGImage' 多次測試後, 應該是 assign 的問題, 請各位指點, 謝謝 編輯記錄
t111 重新編輯於 2008-06-28 10:39:03, 註解 無‧
|
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
|
h@visli
資深會員 發表:103 回覆:429 積分:431 註冊:2004-02-13 發送簡訊給我 |
用的就是Craphics里的TBitmap,Windows單元下的TBitmap是記錄類型,而非Class類型,所以不會jow說的引用單元錯誤。
由于JPEG單元只有DCU文件,所以我在DLL中測試TBitmap.Assign(TBitmap),也出現同樣錯誤。 跟蹤進Graphics單元,發現是TBitmap.Assign方法中導致錯誤: procedure TBitmap.Assign(Source: TPersistent); var DIB: TDIBSection; begin if (Source = nil) or (Source is TBitmap) then begin //真正的Assign操作代碼塊,(省略) end else inherited Assign(Source); //調用TPersistent.Assign方法,(執行的是這里) end; 在if (Source = nil) or (Source is TBitmap) then這句中,(Source is TBitmap)出現了Expression illegal in evaluator錯誤, 所以上面代碼中真正的Assign代碼塊并沒有執行,而是執行 else inherited Assign(Source); 這句。 因此就彈出了TPersistent中的raise EConvertError.CreateResFmt(@SAssignError, [SourceName, ClassName]);異常,也即樓主t111所看到的錯誤提示內容。 ===================引 用 jow 文 章=================== 你使用到的是Windows.pas內的 TBitmap吧! 寫成 Graphics.TBitmap試試.......
------
------------------------ 博采眾家之長,奉獻綿薄之力 ------------------------
編輯記錄
h@visli 重新編輯於 2008-06-28 14:50:41, 註解 無‧
|
t111
一般會員 發表:3 回覆:5 積分:1 註冊:2006-10-30 發送簡訊給我 |
|
t111
一般會員 發表:3 回覆:5 積分:1 註冊:2006-10-30 發送簡訊給我 |
|
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
以下程式碼執行正常, 謹供參考...
[code delphi] library Test068Dll; uses SysUtils, Classes, Graphics, Jpeg; function BMPtoJPE(aBMP: TBitmap): TJPEGImage; Var JPG: TJPEGImage; begin JPG:= TJPEGImage.Create; JPG.Assign(aBMP); Result := JPG; end; {$R *.res} exports BMPtoJPE; begin end. [/code] [code delphi] unit fMain; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Jpeg, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); end; function BMPtoJPE(aBMP: TBitmap): TJPEGImage; external 'Test068Dll.DLL'; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); const src = 'D:\TEST.BMP'; dest = 'D:\TEST.JPG'; var b: TBitmap; j: TJPEGImage; begin if FileExists(src) then begin b := TBitmap.Create; try b.LoadFromFile(src); j := BMPtoJPE(b); try j.SaveToFile(dest); finally FreeAndNil(j); end; finally FreeAndNil(b); end; end; end; end. [/code]
編輯記錄
jow 重新編輯於 2008-06-30 16:32:38, 註解 無‧
|
t111
一般會員 發表:3 回覆:5 積分:1 註冊:2006-10-30 發送簡訊給我 |
已根據 JOW 的方法進行測試, 但問題還是存在, 可能還有其他原因,
我用的是DELPHI 7, 沒有安裝任何UPDATE, 現在傳上測試程序http://delphi.ktop.com.tw/board.php?cid=31&fid=130&tid=94285請指點 |
h@visli
資深會員 發表:103 回覆:429 積分:431 註冊:2004-02-13 發送簡訊給我 |
Delphi 2007下我也试了,一样会出错,我想可能是Delphi的问题。
虽然看不到JPEG的源码,但我想与TBitmap的应该相似, 也即TJpegImage类的Assign方法的第一句应该是: if (Source = nil) or (Source is TJpegImage) then 前一个条件(Source = nil)返回的是False,而第二个条件(Source is TJpegImage)在DLL中运行出現了Expression illegal in evaluator錯誤,也是返回False,因此真正的Assign操作执行不了。 要解决这个问题必须另劈途径,即不要使用TJpegImage这个Class,寻找第三方组件、Class、或算法。
------
------------------------ 博采眾家之長,奉獻綿薄之力 ------------------------ |
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
這個測試碼是我在D7下寫的,
在我機器下可以正常執行... 提供你參考 http://delphi.ktop.com.tw/download.php?download=upload/4869b5d37bc77_Test068.zip |
h@visli
資深會員 發表:103 回覆:429 積分:431 註冊:2004-02-13 發送簡訊給我 |
jow代碼我測試過了,的確可以正常調用。
但我反復比較了我的代碼與jow的代碼,還是沒找出哪里有出入! ===================引 用 jow 文 章=================== 這個測試碼是我在D7下寫的, 在我機器下可以正常執行... 提供你參考 http://delphi.ktop.com.tw/download.php?download=upload/4869b5d37bc77_Test068.zip
------
------------------------ 博采眾家之長,奉獻綿薄之力 ------------------------ |
t111
一般會員 發表:3 回覆:5 積分:1 註冊:2006-10-30 發送簡訊給我 |
|
h@visli
資深會員 發表:103 回覆:429 積分:431 註冊:2004-02-13 發送簡訊給我 |
这是为什么呢?麻烦jow解释一点吧
===================引 用 t111 文 章=================== 謝謝两位的幫助, 問題已解了, 在JOW的程序裏發現, 不是代碼的錯誤, 已是DELPHI設定的問題. 只需要把 DELPHI 中Project ->Options -> Packages 中的選項"Build with runtime packages" 選上, 重新編譯DLL及主程序即.
------
------------------------ 博采眾家之長,奉獻綿薄之力 ------------------------ |
maomfh
初階會員 發表:3 回覆:10 積分:27 註冊:2008-01-05 發送簡訊給我 |
問題的原因是,如果當使用靜態連結模式, EXE檔和 DLL檔,各自都會有一套物件體系, TObject -> TPersistent ->TGraphis->TBitmap (實際物件繼承不是這樣,只是舉例),也就是 EXE和DLL 會對這些類別都產生自己的VMT表,連類別的程式都有二套一樣的, 當你從EXE 呼叫 DLL中的 函數,且傳入EXE檔生成的物件. 而在DLL中的函數把參數拿來和自己的物件體系比較, 就會發生 TBitmap物件(Born in EXE) 不是 TBitmap類別(Born in DLL), 所以當DLL中的 AssignTo 函數去做 if aParam is TBitmap 時就會傳回 False, IS這個運算子是比較兩類別的VMT地址.
如果改成利用動態連結,則因為EXE 和 DLL 都使用 Borland執行期程式庫. 所以物件體系只會有一套, DLL和EXE都共用同個TObject, TBitmap, TPicture. 等等的類別, 而不是EXE一個 TObject類別, DLL一個TObject類別,所以程式就能正常. 那靜態連結DLL是不是就不能使用 "物件" 當傳遞和傳回的參數,那可能有另外的方法. 也許可以利用 介面(Interface), 也就是為什麼會有 COM 的出現.
------
Maomfh
編輯記錄
maomfh 重新編輯於 2008-08-07 17:04:39, 註解 無‧
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |