dbo*_*eam 8 c++ dll 64-bit name-mangling
我试图将32位dll(和应用程序)移植到64位,我已经设法构建它没有错误.当我尝试使用我的64位应用程序加载它时,我注意到导出的函数名称不同.这是我导出函数的方式:
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) long __stdcall Connect(char * name, long size);
#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)
在Dependency Walker中,导出的函数具有以下格式:
32位: _Connect@8
64位: Connect
在使用dll的应用程序中,我显式加载了dll(LoadLibrary成功)但GetProcAddress因64位而失败,因为它找不到具有提供名称的函数.
在我们的应用程序中,我保留函数名称如下:
#define ConnectName "_Connect@8"
...
GetProcAddress(Dll, ConnectName);
Run Code Online (Sandbox Code Playgroud)
所以我想知道是否可以为32位和64位dll导出相同的函数名称,或者这是一个坏主意?或者我需要在我的应用程序中执行以下操作:
#if _WIN64
#define ConnectName "Connect"
#else
#define ConnectName "_Connect@8"
#endif
Run Code Online (Sandbox Code Playgroud)
我感谢任何帮助.
一个选项,你必须函数名导出没有任何装饰(独立从您在86使用的特定调用约定__stdcall,__cdecl或其他),并用相同的未修饰的名字在这两个x86和x64版本,是导出使用您的DLL函数DEF文件.
例如,您可以将类似的.DEF文件添加到您的项目中:
LIBRARY YOURDLL
EXPORTS
Connect @1
AnotherFunction @2
... etc. ...
Run Code Online (Sandbox Code Playgroud)
Repro跟随
在Visual Studio中创建一个空的解决方案(我使用VS2013),并在其中创建一个空的Win32控制台项目(测试客户端)和一个空的Win32 DLL项目(测试DLL).
在DLL项目中添加此NativeDll.def .DEF文件:
LIBRARY NATIVEDLL
EXPORTS
SayHello @1
Run Code Online (Sandbox Code Playgroud)
NativeDll.cpp在DLL项目中添加此C++源代码:
///////////////////////////////////////////////////////////////////////////////
//
// NativeDll.cpp -- DLL Implementation Code
//
///////////////////////////////////////////////////////////////////////////////
#include <Windows.h>
#include <atldef.h>
#include <atlstr.h>
//
// Test function exported from the DLL
//
extern "C" HRESULT WINAPI SayHello(PCWSTR name)
{
//
// Check for null input string pointer
//
if (name == nullptr)
{
return E_POINTER;
}
try
{
//
// Build a greeting message and show it in a message box
//
CString message;
message.Format(L"Hello %s from the native DLL!", name);
MessageBox(nullptr, message, L"Native DLL Test", MB_OK);
// All right
return S_OK;
}
//
// Catch exceptions and convert them to HRESULT codes
//
catch (const CAtlException& ex)
{
return static_cast<HRESULT>(ex);
}
catch (...)
{
return E_FAIL;
}
}
Run Code Online (Sandbox Code Playgroud)
NativeClient.cpp在客户端测试项目中添加此C++源代码:
///////////////////////////////////////////////////////////////////////////////
//
// NativeClient.cpp -- EXE Test Client Code
//
///////////////////////////////////////////////////////////////////////////////
#include <Windows.h>
//
// Prototype of the function to be loaded from the DLL
//
typedef HRESULT (WINAPI *SayHelloFuncPtr)(PCWSTR /* name */);
//
// Simple RAII wrapper on LoadLibrary()/FreeLibrary().
//
class ScopedDll
{
public:
//
// Load the DLL
//
ScopedDll(PCWSTR dllFilename) throw()
: m_hDll(LoadLibrary(dllFilename))
{
}
//
// Unload the DLL
//
~ScopedDll() throw()
{
if (m_hDll)
{
FreeLibrary(m_hDll);
}
}
//
// Was the DLL loaded successfully?
//
explicit operator bool() const throw()
{
return (m_hDll != nullptr);
}
//
// Get the DLL handle
//
HINSTANCE Get() const throw()
{
return m_hDll;
}
//
// *** IMPLEMENTATION ***
//
private:
//
// The wrapped raw DLL handle
//
HINSTANCE m_hDll;
//
// Ban copy
//
private:
ScopedDll(const ScopedDll&) = delete;
ScopedDll& operator=(const ScopedDll&) = delete;
};
//
// Display an error message box
//
inline void ErrorMessage(PCWSTR errorMessage) throw()
{
MessageBox(nullptr, errorMessage, L"*** ERROR ***", MB_OK | MB_ICONERROR);
}
//
// Test code calling the DLL function via LoadLibrary()/GetProcAddress()
//
int main()
{
//
// Return codes
//
static const int kExitOk = 0;
static const int kExitError = 1;
//
// Load the DLL with LoadLibrary().
//
// NOTE: FreeLibrary() automatically called thanks to RAII!
//
ScopedDll dll(L"NativeDll.dll");
if (!dll)
{
ErrorMessage(L"Can't load the DLL.");
return kExitError;
}
//
// Use GetProcAddress() to access the DLL test function.
// Note the *undecorated* "SayHello" function name!!
//
SayHelloFuncPtr pSayHello
= reinterpret_cast<SayHelloFuncPtr>(GetProcAddress(dll.Get(),
"SayHello"));
if (pSayHello == nullptr)
{
ErrorMessage(L"GetProcAddress() failed.");
return kExitError;
}
//
// Call the DLL test function
//
HRESULT hr = pSayHello(L"Connie");
if (FAILED(hr))
{
ErrorMessage(L"DLL function call returned failure HRESULT.");
return kExitError;
}
//
// All right
//
return kExitOk;
}
Run Code Online (Sandbox Code Playgroud)
构建整个解决方案(.EXE和.DLL)并运行本机.EXE客户端.
这是我在电脑上得到的:

它在没有修改的情况下工作,并且在x86和x64版本上都使用未修饰的函数名称(仅SayHello).