線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:5354
推到 Plurk!
推到 Facebook!

cannot assign a TBitmap to a TJpegImage

答題得分者是:jow
t111
一般會員


發表:3
回覆:5
積分:1
註冊:2006-10-30

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-06-28 10:27:00 IP:122.100.xxx.xxx 訂閱
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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-06-28 14:04:00 IP:123.193.xxx.xxx 未訂閱
你使用到的是Windows.pas內的 TBitmap吧!

寫成 Graphics.TBitmap試試.......
h@visli
資深會員


發表:103
回覆:429
積分:431
註冊:2004-02-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-06-28 14:47:14 IP:119.122.xxx.xxx 未訂閱
用的就是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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-06-30 10:42:11 IP:122.100.xxx.xxx 訂閱
謝謝 两位意見
t111
一般會員


發表:3
回覆:5
積分:1
註冊:2006-10-30

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-06-30 11:12:06 IP:122.100.xxx.xxx 訂閱
我也曾經 用 h@visli 所用的方法 TBitMap.assign(TBitMap) 測試過, 同様在這個地方出現錯, cannot assign a TBitmap to a TBitmap
讓我不明白的是, 為何只在DLL中才會出錯誤, 引用錯誤單元這個可能性較大, 有可能是更深層的單元引用錯嗎?
編輯記錄
t111 重新編輯於 2008-06-30 11:20:53, 註解 無‧
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-06-30 16:29:27 IP:203.70.xxx.xxx 未訂閱
以下程式碼執行正常, 謹供參考...

[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

發送簡訊給我
#7 引用回覆 回覆 發表時間:2008-06-30 19:23:50 IP:122.100.xxx.xxx 訂閱
已根據 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

發送簡訊給我
#8 引用回覆 回覆 發表時間:2008-07-01 11:06:21 IP:119.122.xxx.xxx 未訂閱
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

發送簡訊給我
#9 引用回覆 回覆 發表時間:2008-07-01 12:45:13 IP:203.70.xxx.xxx 未訂閱
這個測試碼是我在D7下寫的,
在我機器下可以正常執行...

提供你參考

http://delphi.ktop.com.tw/download.php?download=upload/4869b5d37bc77_Test068.zip
h@visli
資深會員


發表:103
回覆:429
積分:431
註冊:2004-02-13

發送簡訊給我
#10 引用回覆 回覆 發表時間:2008-07-01 14:29:49 IP:119.122.xxx.xxx 未訂閱
jow代碼我測試過了,的確可以正常調用。
但我反復比較了我的代碼與jow的代碼,還是沒找出哪里有出入!

===================引 用 jow 文 章===================
這個測試碼是我在D7下寫的,
在我機器下可以正常執行...

提供你參考

http://delphi.ktop.com.tw/download.php?download=upload/4869b5d37bc77_Test068.zip
------
------------------------
博采眾家之長,奉獻綿薄之力
------------------------
t111
一般會員


發表:3
回覆:5
積分:1
註冊:2006-10-30

發送簡訊給我
#11 引用回覆 回覆 發表時間:2008-07-01 15:02:54 IP:202.86.xxx.xxx 訂閱
謝謝两位的幫助,
問題已解了, 在JOW的程序裏發現, 不是代碼的錯誤,
已是DELPHI設定的問題. 只需要把 DELPHI 中Project ->Options -> Packages
中的選項"Build with runtime packages" 選上, 重新編譯DLL及主程序即.
具體原因不明, 但不選時所生成的DLL文件為210K, 但選後只有8K
h@visli
資深會員


發表:103
回覆:429
積分:431
註冊:2004-02-13

發送簡訊給我
#12 引用回覆 回覆 發表時間:2008-07-02 08:55:05 IP:119.122.xxx.xxx 未訂閱
这是为什么呢?麻烦jow解释一点吧

===================引 用 t111 文 章===================
謝謝两位的幫助,
問題已解了, 在JOW的程序裏發現, 不是代碼的錯誤,
已是DELPHI設定的問題. 只需要把 DELPHI 中Project ->Options -> Packages
中的選項"Build with runtime packages" 選上, 重新編譯DLL及主程序即.
------
------------------------
博采眾家之長,奉獻綿薄之力
------------------------
maomfh
初階會員


發表:3
回覆:10
積分:27
註冊:2008-01-05

發送簡訊給我
#13 引用回覆 回覆 發表時間:2008-08-07 17:00:12 IP:218.163.xxx.xxx 訂閱
問題的原因是,如果當使用靜態連結模式, 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, 註解 無‧
系統時間:2024-05-02 21:33:33
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!