COM进程中DLL中的DllMain出现问题
An issue with DllMain in COM in-proc DLL
我开发了一个基于proc COM服务器的C++DLL,并成功地用MinGW+MSYS编译了它。如果我用--enable-stdcall-fixup -Wl,DLLMain.def
开关编译它,那么与COM服务器相关的一切都会像符咒一样工作。然而,通过这种方式,一些符号被导出了两次:
"dlltool-z output.def--导出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
在没有--enable-stdcall-fixup
编译开关的情况下,DllMain
例程未导出的原因是什么?使用MinGW+MSYS构建进程内COM服务器有什么特别的技巧吗?
解决方案#1
正如Hans在回答中所建议的那样,可以在.def文件中使用重命名语法,如下所示:
EXPORTS
DllGetClassObject = DllGetClassObject@12
DllCanUnloadNow = DllCanUnloadNow@0
DllRegisterServer = DllRegisterServer@0
DllUnregisterServer = DllUnregisterServer@0
在Haskell中构建和使用Win32 DLL的指南也提出了同样的建议。
解决方案#2
另一种方法是利用--kill-at
链接器开关剥离@nn部分:
--kill-at
If given, the stdcall suffixes (@nn) will be stripped from symbols
before they are exported.
我对您的构建工具了解不够,但可以推断。链接器正在抱怨,因为您要求导出"DllRegisterServer",但编译器实际生成了标识符DllRegisterServer@0"根据stdcall调用约定的要求。这是不匹配的。--enable stdcall fixup选项是一种解决方法,将链接器置于"模糊搜索模式",并允许它查找匹配项。
获得两个导出是草率的,但实际上并不是问题,无论代码使用这些入口点,都会要求正确的入口点。绝对不要尝试--导出所有符号。您唯一可以尝试的另一件事是在.def文件中使用重命名语法,不确定您的链接器是否支持它:
DllUnregisterServer=DllUnregisterServer@0 @5 PRIVATE
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 一个关于在C++中重载布尔运算符的问题
- 首要问题的答案让值班员搞错了
- setlocale的C++土耳其字符串问题
- 如何重构类层次结构以避免菱形问题
- 基于boost的程序的静态链接——zlib问题
- 在VC++中从DLLMAIN内部调用D3D的CREATEDEVICE时,它会创建一个死锁(loaderlock?)。有没有办法克服这个问题?最终目标内
- COM进程中DLL中的DllMain出现问题