有没有办法找到要在 GetProcAddress 中使用的 C++ 错误名称? [英] Is there a way to find the C++ mangled name to use in GetProcAddress?

查看:24
本文介绍了有没有办法找到要在 GetProcAddress 中使用的 C++ 错误名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 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 里面T GetProcAddress(HMODULE h, const char* name),宏__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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆