有没有办法找到要在 GetProcAddress 中使用的 C++ 错误名称? [英] Is there a way to find the C++ mangled name to use in GetProcAddress?
问题描述
在 C++ 中使用 GetProcAddress
的常见解决方案"是externC",但这会破坏重载.名称修改允许多个函数共存,只要它们的签名不同.但是有没有办法为 GetProcAddress
找到这些损坏的名称?
The common "solution" to use GetProcAddress
with C++ is "extern "C", but that breaks overloading. Name mangling allows multiple functions to co-exist, as long as their signature differs. But is there a way to find these mangled names for GetProcAddress
?
推荐答案
VC++ 编译器知道自己的名称修改方案,为什么不使用它呢?template
,宏__FUNCDNAME__
包含GetProcAddress
的重整名称.这包括 T
部分.因此,在 GetProcAddress
void(*)(int)
名称的子字符串.由此,我们可以轻松推导出 void foo(int);
The VC++ compiler knows its own name mangling scheme, so why not use that? Inside template<typename T> T GetProcAddress(HMODULE h, const char* name)
, the macro __FUNCDNAME__
contains the mangled name of GetProcAddress
. That includes the T
part. So, inside GetProcAddress<void(*)(int)
, we have a substring with the mangled name of void(*)(int)
. From that, we can trivially derive the mangled name of void foo(int);
此代码依赖于 VC++ 宏 __FUNCDNAME__
.对于 MinGW,你需要基于 .__PRETTY_FUNCTION__
而不是
This code relies on the VC++ macro __FUNCDNAME__
. For MinGW you'd need to base this on .__PRETTY_FUNCTION__
instead
FARPROC GetProcAddress_CppImpl(HMODULE h, const char* name, std::string const& Signature)
{
// The signature of T appears twice in the signature of T GetProcAddress<T>(HMODULE, const char*)
size_t len = Signature.find("@@YA");
std::string templateParam = Signature.substr(0, len);
std::string returnType = Signature.substr(len+4);
returnType.resize(templateParam.size()); // Strip off our own arguments (HMODULE and const char*)
assert(templateParam == returnType);
// templateParam and returnType are _pointers_ to functions (P6), so adjust to function type (Y)
std::string funName = "?" + std::string(name) + "@@Y" + templateParam.substr(2);
return ::GetProcAddress(h, funName.c_str());
}
template <typename T>
T GetProcAddress(HMODULE h, const char* name)
{
// Get our own signature. We use `const char* name` to keep it simple.
std::string Signature = __FUNCDNAME__ + 18; // Ignore prefix "??$GetProcAddress@"
return reinterpret_cast<T>(GetProcAddress_CppImpl(h, name, Signature));
}
// Showing the result
struct Dummy { };
__declspec(dllexport) void foo( const char* s)
{
std::cout << s;
}
__declspec(dllexport) void foo( int i, Dummy )
{
std::cout << "Overloaded foo(), got " << i << std::endl;
}
__declspec(dllexport) void foo( std::string const& s )
{
std::cout << "Overloaded foo(), got " << s << std::endl;
}
__declspec(dllexport) int foo( std::map<std::string, double> volatile& )
{
std::cout << "Overloaded foo(), complex type\n";
return 42;
}
int main()
{
HMODULE h = GetModuleHandleW(0);
foo("Hello, ");
auto pFoo1 = GetProcAddress<void (*)( const char*)>(h, "foo");
// This templated version of GetProcAddress is typesafe: You can't pass
// a float to pFoo1. That is a compile-time error.
pFoo1(" world\n");
auto pFoo2 = GetProcAddress<void (*)( int, Dummy )>(h, "foo");
pFoo2(42, Dummy()); // Again, typesafe.
auto pFoo3 = GetProcAddress<void (*)( std::string const& )>(h, "foo");
pFoo3("std::string overload\n");
auto pFoo4 = GetProcAddress<int (*)( std::map<std::string, double> volatile& )>(h, "foo");
// pFoo4 != NULL, this overload exists.
auto pFoo5 = GetProcAddress<void (*)( float )>(h, "foo");
// pFoo5==NULL - no such overload.
}
这篇关于有没有办法找到要在 GetProcAddress 中使用的 C++ 错误名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!