gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 15:09:02 26 4
gpt4 key购买 nike

我有一个加载 DLL 的应用程序,该 DLL 使用 Delphi GDI+ Library 。该应用程序在卸载 DLL 时挂起(调用 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 。这些函数在单元 initialization 中调用和finalization部分,分别。对于图书馆项目,代码位于 initializationfinalization单元的各个部分从 DllMain 开始执行.

看来您使用的 GdiPlus 库从未打算从库中使用。但作为一般规则,在编写库代码时,您应该注意 DllMain 周围的限制。并确保您将代码放置在 initialization 中和finalization部分尊重这一点。我认为这个 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;

此代码通过确保它不会调用 GdiplusStartup 来遵守规则。和GdiplusShutdown来自DllMain 。相反,它将责任留给任何使用 WinApi.GDIPOBJ 的库的作者。确保GdiplusStartupGdiplusShutdown在适当的时间被调用。

如果我是你,我会选择上面列出的三个要点选项之一。第三个选项不太实用,但前两个是不错的选择。如果是我,我会选择第一个选项并修改 initializationfinalization代码在你的 GdiPlus库看起来更像 WinApi.GDIPOBJ 中的库.

关于delphi - 使用 GdiPlus 卸载 DLL 时程序挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34871348/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com