gpt4 book ai didi

c++ - COM 进程内 DLL 中的 DllMain 问题

转载 作者:行者123 更新时间:2023-11-30 03:04:10 24 4
gpt4 key购买 nike

我开发了一个基于 C++ DLL 的进程内 COM 服务器,并使用 MinGW + MSYS 成功编译了它。如果我用 --enable-stdcall-fixup -Wl,DLLMain.def 编译它,那么与 COM 服务器相关的所有内容都会像一个魅力一样工作。然而,这样一些符号被导出了两次:

'dlltool -z output.def --export-all-symbols libCOMTest.dll' 产生:

EXPORTS
...
DeleteCriticalSection@4 @ 14
DllCanUnloadNow @ 15 DATA
DllCanUnloadNow@0 @ 16
DllGetClassObject @ 17 DATA
DllGetClassObject@12 @ 18
DllMain @ 19 DATA
DllMainCRTStartup@12 @ 20
DllRegisterServer @ 21 DATA
DllRegisterServer@0 @ 22
DllUnregisterServer @ 23 DATA
DllUnregisterServer@0 @ 24
EnterCriticalSection@4 @ 25
...

链接器会生成一些警告:

Warning: resolving _DllMain by linking to _DllMain@12
Use --enable-stdcall-fixup to disable these warnings
Use --disable-stdcall-fixup to disable these fixups
Warning: resolving _DllGetClassObject by linking to _DllGetClassObject@12
Warning: resolving _DllCanUnloadNow by linking to _DllCanUnloadNow@0
Warning: resolving _DllRegisterServer by linking to _DllRegisterServer@0
Warning: resolving _DllUnregisterServer by linking to _DllUnregisterServer@0

如果我省略这些编译器选项,DllMain 例程将无法导出,所以我什至无法使用 regsvr32 实用程序注册我的 COM 服务器。

下面是 libCOMTest.dll 的一些导出符号:

EXPORTS
...
DeleteCriticalSection@4 @ 14
DllCanUnloadNow@0 @ 15
DllGetClassObject@12 @ 16
DllMainCRTStartup@12 @ 17
DllRegisterServer@0 @ 18
DllUnregisterServer@0 @ 19
EnterCriticalSection@4 @ 20
...

如您所见,列表中没有 DllMain 例程。

我的 .def 文件如下所示:

LIBRARY         libCOMTest
DESCRIPTION 'libCOMTest in-proc server'

EXPORTS
DllMain @1 PRIVATE
DllGetClassObject @2 PRIVATE
DllCanUnloadNow @3 PRIVATE
DllRegisterServer @4 PRIVATE
DllUnregisterServer @5 PRIVATE

DllMain 例程在没有 --enable-stdcall-fixup 编译开关的情况下未导出的原因是什么?使用 MinGW + MSYS 构建进程内 COM 服务器是否有任何特殊技巧?

解决方案#1

正如 Hans 在他的回答中所建议的,可以在 .def 文件中使用重命名语法,如下所示:

EXPORTS
DllGetClassObject = DllGetClassObject@12
DllCanUnloadNow = DllCanUnloadNow@0
DllRegisterServer = DllRegisterServer@0
DllUnregisterServer = DllUnregisterServer@0

guide to building and using Win32 DLLs in Haskell建议是一样的。

解决方案#2

另一种方法是使用--kill-at 链接器开关去除@nn 部分:

--kill-at
If given, the stdcall suffixes (@nn) will be stripped from symbols
before they are exported.

最佳答案

我对您的构建工具了解不够,但可以推断。链接器提示是因为您要求导出“DllRegisterServer”,但编译器实际上根据 stdcall 调用约定生成了标识符“DllRegisterServer@0”。那是不匹配。 --enable-stdcall-fixup 选项是一种解决方法,将链接器置于“模糊搜索模式”并允许它找到匹配项。

得到两个导出是草率的,但实际上不是问题,无论代码使用这些入口点总是会要求正确的入口点。一定要尝试不使用 --export-all-symbols。您唯一可以尝试的另一件事是在 .def 文件中使用重命名语法,不确定您的链接器是否支持它:

        DllUnregisterServer=DllUnregisterServer@0  @5  PRIVATE

关于c++ - COM 进程内 DLL 中的 DllMain 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8886143/

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