头文件如下所示
#define CoverWinAPI extern "C" __declspec(dllexport)
CoverWinAPI BOOL RunDll();
CoverWinAPI void ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,PROC pfnCurrent,PROC pfnNew,HMODULE hmodCaller);
#pragma comment(linker,"/export:MyCreateWindowExW=_MyCreateWindowExW@48")
CoverWinAPI HWND WINAPI MyCreateWindowExW(
_In_opt_ DWORD dwExStyle,
_In_opt_ LPCWSTR lpClassName,
_In_opt_ LPCWSTR lpWindowName,
_In_ DWORD dwStyle,
_In_ int X,
_In_ int Y,
_In_ int nWidth,
_In_ int nHeight,
_In_opt_ HWND hWndParent,
_In_opt_ HMENU hMenu,
_In_opt_ HINSTANCE hInstance,
_In_opt_ LPVOID lpParam);
当我不使用#语用注释时,导出函数名是_MyCreateWindowExW@48。
但是当我使用#pragma comment(linker,"/export:MyCreateWindowExW=_MyCreateWindowExW@48")
时,MSVC编译失败并显示unresolved external symbol _MyCreateWindowExW@48
。是什么导致了这个错误?
发布于 2022-06-11 09:07:07
您遇到的问题是编译器修饰函数名称的方式造成的。_MyCreateWindowExW@48
是一个x86风格的修饰名称,只对x86 build only 有效,它的x64对应项只是MyCreateWindowExW
(x64只有一个类似于__cdecl
的调用约定,即调用方负责管理堆栈分配)。
与正式文档相反,导出#pragma
和/EXPORT
链接器选项都不使用未修饰的名称,它们都期望名称得到完整的修饰。我是这里提到的。
小票
有几种从Dll导出的方法,例如:
__declspec(dllexport)
#pragma comment(linker,"/export:...")
或link.exe /EXPORT
通常只使用其中一个就足够了,所以在您的示例中,__declspec(dllexport)
是多余的,考虑到它导出了一个修饰的名称,这不是您想要的。
解决方案1(海事组织繁琐)
使用#ifdef
为每个平台提供适当的修饰名称:
#define CoverWinAPI extern "C"
CoverWinAPI BOOL RunDll();
CoverWinAPI void ReplaceIATEntryInOneMod(PCSTR pszCalleeModName, PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller);
#ifndef _WIN64
#pragma comment(linker,"/export:MyCreateWindowExW=_MyCreateWindowExW@48")
#else
#pragma comment(linker,"/export:MyCreateWindowExW")
#endif
CoverWinAPI HWND WINAPI MyCreateWindowExW(...);
解决方案2(建议)
将DEF文件添加到项目中:
LIBRARY CoverWinAPI
EXPORTS
MyCreateWindowExW
RunDll
ReplaceIATEntryInOneMod
然后您的声明可以重写如下:
#define CoverWinAPI WINAPI
BOOL CoverWinAPI RunDll();
void CoverWinAPI ReplaceIATEntryInOneMod(PCSTR pszCalleeModName, PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller);
HWND CoverWinAPI MyCreateWindowExW(...);
这是因为链接器确实试图匹配DEF文件条目与修饰和未修饰的名称。
https://stackoverflow.com/questions/72445583
复制相似问题