MSa*_*ers 5 windows visual-c++
GetProcAddress与C++ 一起使用的常见"解决方案" 是"extern"C",但它打破了重载.名称修改允许多个函数共存,只要它们的签名不同.但是有没有办法找到这些受损的名称GetProcAddress?
VC++编译器知道自己的名称修改方案,为什么不使用它?在里面template<typename T> T GetProcAddress(HMODULE h, const char* name),宏__FUNCDNAME__包含了错误的名称GetProcAddress.这包括T部分.所以,在里面GetProcAddress<void(*)(int),我们有一个带有错误名称的子字符串void(*)(int).从那以后,我们可以简单地得出被破坏的名字void foo(int);
此代码依赖于VC++宏__FUNCDNAME__.对于MinGW的你需要此基础上.__PRETTY_FUNCTION__,而不是
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.
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3211 次 |
| 最近记录: |