调用DLL中jpg转bmp函数实现图片特技显示效果出现运行时错误怎么解决(50)

  • 主题发起人 主题发起人 sghff110
  • 开始时间 开始时间
S

sghff110

Unregistered / Unconfirmed
GUEST, unregistred user!
{$R *.dfm}function bmpfromjpg(jpgf:string):Tbitmap;stdcall;external'jpgtobmp.dll';//静态调用procedure TForm1.Button1Click(Sender: TObject); var myb:TBitmap; i,w1,h1:integer;begin myb:=TBitmap.Create ; try myb:=bmpfromjpg('g:/tupian/funiu.jpg'); for i:=0 to 30 do //打开窗帘特效 begin ...... end; finally myb.Free ; end;end;基本实现了特显功能,但往往在完成显示之后不久或尚未全部显示(剩余1/5)就出现运行时调试器异常通知对话框:Project Project1.exe raised exception class EAccessViolation with message'Access violation at address 7C93B1FA in modal'ntdll.ll'.Write of address 00000010'.但是若把DLL中的函数直接写成自定义形式调用则不会出现这个异常,很正常显示。
 
function bmpfromjpg(jpgf:string):Tbitmap;stdcall;---->function bmpfromjpg(jpgf:PChar):Tbitmap;stdcall;调用:myb:=bmpfromjpg( PChar('g:/tupian/funiu.jpg') );
 
你DLL中函数定义也改成了PChar了吗?
 
您这个回答倒是提醒我了。即带有STRING长字符串的参数时,要么USES 头一个加SHAREMem,要么变Pchar。但这两种情况我都试了,两种都解决不了上述问题。另外同时存在在展开图像时有少许抖动……到底怎么回事呀.……znxia大侠,我希望把源码发给您。能告诉QQ吗。myqq:729851670
 
根据有关资料,“Eaccess Violation”属于“无效的内存处理操作”。但不知怎样调试、处理,没有一点这方面的尝试。哪位高手愿指点一下呀……
 
DLL直接返回对象时是有可能出错的,这是因为程序和DLL用了不同的VCL,就是相当于一个接口的不同实例,所以只要是从DLL里返回VCL相关的对象都会出错。有两种方法可以解决:1、在Controls单元的implementation前面声明一个GetControlAtom方法{...}implementationfunction GetControlAtom: Pointer;begin Result := @ControlAtom;end;然后在DLL里实现并导出以下两个过程procedure DLLInitialize(App : TApplication; Scr : TScreen; RealControlAtom :Integer);var x : pointer; p : ^Word;begin If (OldApp = Nil) Then Begin // store away the current application, screen and control atom OldApp := Application; OldScreen := Screen; p := GetControlAtom; OldControlAtom := p^; // Assign the EXE's application, screen and control atom Application := App; Screen := Scr; p^ := RealControlAtom; end; end;procedure DLLFinalize;var p: ^Word; begin // restore the DLL's application, screen and control atom p := GetControlAtom; p^ := OldControlAtom; Screen := OldScreen; Application := OldApp; end;这两个过程的作用,一个是初始化DLL时将宿主程序与DLL的全局原子ControlAtom同步,另一个是DLL释放前还原相关内容。然后你就可以在DLL里用函数返回VCL对象了,此方法也适用于在DLL里创建窗体在Dock到宿主的Panel里,反正最关键的是ControlAtom同步。2、不使用VCL对象作为返回值很简单,可以用内存来做交换,例如转换图像后,申请一块内存,将转换后的图像写入这块内存,方法就不多说了,用流操作或Move都可以,关键是返回指针地址和长度。function bmp2jpg(filename: PChar; var Ptr: Pointer; var Size: Integer): Boolean;var stream: TmemoryStream;begin try {转换} except result := false; exit; end; Stream := TMemoryStream.Create; jpg.saveToStream(Stream); Size := Stream.Size; GetMem(Ptr, Size); Stream.Position := 0; Stream.Read(Ptr^, Size); Stream.Free; Result := True;end;本来不想写代码的,算了,从内存里读出来你就自己写吧。
 
补充一下:在DLL里声明全局变量var OldApp : TApplication; OldScreen : TScreen; OldControlAtom : TAtom; exprots ....;begin OldApp := nil; OldScreen := nil; OldControlAtom := 0;end;
 
cmd9x实在是高手啊……感谢!!
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
612
import
I
后退
顶部