加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

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

发布时间:2020-12-15 09:31:43 所属栏目:大数据 来源:网络整理
导读:我有一个应用程序加载使用 Delphi GDI+ Library的DLL.此应用程序在卸载DLL时挂起(Calling FreeLibrary). 我将问题跟踪到GdiPlus.pas单元终结部分,该部分调用GdiPlusShutdown,它永远不会返回. 如何避免这种僵局? 解决方法 GdiplusStartup 功能的文档说明了这
我有一个应用程序加载使用 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中的代码.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读