delphi – 使用GdiPlus卸载DLL时程序挂起

delphi – 使用GdiPlus卸载DLL时程序挂起,第1张

概述我有一个应用程序加载使用 Delphi GDI+ Library的DLL.此应用程序在卸载DLL时挂起(Calling FreeLibrary). 我将问题跟踪到GdiPlus.pas单元终结部分,该部分调用GdiPlusShutdown,它永远不会返回. 如何避免这种僵局? GdiplusStartup功能的文档说明了这一点: Do not call GdiplusStartup or Gdip 我有一个应用程序加载使用 Delphi GDI+ Library的DLL.此应用程序在卸载DLL时挂起(Calling FreeLibrary).

我将问题跟踪到GdiPlus.pas单元终结部分,该部分调用GdiPlusShutdown,它永远不会返回.

如何避免这种僵局?

解决方法 GdiplusStartup功能的文档说明了这一点:

Do not call Gdiplusstartup or GdiplusShutdown in DllMain or in any
function that is called by DllMain. If you want to create a DLL that
uses GDI+,you should use one of the following techniques to
initialize GDI+:

Require your clIEnts to call Gdiplusstartup before they call the functions in your DLL and to call GdiplusShutdown when they have
finished using your DLL. Export your own startup function that calls Gdiplusstartup and your own shutdown function that calls GdiplusShutdown. Require your clIEnts
to call your startup function before they call other functions in your
DLL and to call your shutdown function when they have finished using
your DLL. Call Gdiplusstartup and GdiplusShutdown in each of your functions that make GDI+ calls.

通过将此Delphi GdiPlus库编译为DLL,您违反了Gdiplusstartup和GdiplusShutdown的规则.这些函数分别在单元初始化和完成部分中调用.对于库项目,单元的初始化和完成部分中的代码从DllMain执行.

您使用的GdiPlus库似乎从未打算从库中使用.但作为一般规则,在编写库代码时,您应该了解DllMain的限制,并确保您在初始化和完成部分中的代码尊重它.我认为这个GdiPlus库在这方面失败了.

相比之下,看一下Delphi RTL的WinAPI.GDIPOBJ单元中的代码:

initialization  if not Islibrary then  begin    // Initialize Startupinput structure    Startupinput.DeBUGEventCallback := nil;    Startupinput.SuppressBackgroundThread := False;    Startupinput.SuppressExternalCodecs   := False;    Startupinput.Gdiplusversion := 1;    Gdiplusstartup(gdiplusToken,@Startupinput,nil);  end;finalization  if not Islibrary then  begin    if Assigned(GenericSansserifFontFamily) then      GenericSansserifFontFamily.Free;    if Assigned(GenericserifFontFamily) then      GenericserifFontFamily.Free;    if Assigned(GenericMonospaceFontFamily) then      GenericMonospaceFontFamily.Free;    if Assigned(GenericTypographicStringFormatBuffer) then      GenericTypographicStringFormatBuffer.free;    if Assigned(GenericDefaultStringFormatBuffer) then      GenericDefaultStringFormatBuffer.Free;    GdiplusShutdown(gdiplusToken);  end;

此代码通过确保它不从DllMain调用Gdiplusstartup和GdiplusShutdown来遵守规则.相反,它留给使用WinAPI.GDIPOBJ的任何库的作者的责任,以确保在适当的时间调用Gdiplusstartup和GdiplusShutdown.

如果我是你,我会选择上面列出的三个项目符号选项之一.这些选项中的第三个不太实用,但前两个是不错的选择.如果是我,我会选择第一个选项并修改GdiPlus库中的初始化和终结代码,使其看起来更像WinAPI.GDIPOBJ中的代码.

总结

以上是内存溢出为你收集整理的delphi – 使用GdiPlus卸载DLL时程序挂起全部内容,希望文章能够帮你解决delphi – 使用GdiPlus卸载DLL时程序挂起所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1265337.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存