Last active
January 26, 2021 20:04
-
-
Save ttsuki/cf4aeb5772715b98c39d30d136f36980 to your computer and use it in GitHub Desktop.
WrapMemFuncAsRawFunctionPointer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "WrapMemFuncAsRawFunctionPointer.hpp" | |
class Interface | |
{ | |
public: | |
virtual ~Interface() = default; | |
virtual int A() =0; | |
virtual int B(const int&) = 0; | |
virtual int& C(int&&, float) = 0; | |
}; | |
class InterfaceImpl : public Interface | |
{ | |
public: | |
int x{12}; | |
int A() override { return 10; } | |
int B(const int&) override { return 11; } | |
int& C(int&&, float) override { return x; } | |
}; | |
int main() | |
{ | |
InterfaceImpl a{}; | |
// FuncA is `int &(__stdcall *)(Interface *, int&&, float)` | |
auto FuncA = WrapMemberFunctionAsRawFunctionPointer<&Interface::C>(); | |
FuncA(&a, 1, 1.2f) = 15; | |
int result = FuncA(&a, 1, 1.2f); | |
return result; // 15 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <utility> | |
namespace detail | |
{ | |
enum struct CallConv | |
{ | |
Cdecl, | |
StdCall, | |
}; | |
template <class TResult, CallConv X, class...TArgs> | |
struct FunctionPointerWithCallingConvention; | |
template <class TResult, class...TArgs> | |
struct FunctionPointerWithCallingConvention<TResult, CallConv::Cdecl, TArgs...> | |
{ | |
using Type = TResult (__cdecl*)(TArgs ...); | |
}; | |
template <class TResult, class...TArgs> | |
struct FunctionPointerWithCallingConvention<TResult, CallConv::StdCall, TArgs...> | |
{ | |
using Type = TResult (__stdcall*)(TArgs ...); | |
}; | |
template <class TFunc> | |
struct ProxyFunction; | |
template <class TResult, class TInterface, class...TArgs> | |
struct ProxyFunction<TResult (TInterface::*)(TArgs ...)> | |
{ | |
template <TResult (TInterface::* TMemFunc)(TArgs ...), CallConv TCallConv> | |
static auto GetWrapped() | |
-> typename FunctionPointerWithCallingConvention<TResult, TCallConv, TInterface*, TArgs...>::Type | |
{ | |
return [](TInterface* instance, TArgs ...args) -> decltype(auto) | |
{ | |
return (instance->*TMemFunc)(std::forward<TArgs>(args)...); | |
}; | |
} | |
}; | |
template <auto TMemFunc, CallConv TCallConv = CallConv::StdCall> | |
constexpr auto WrapMemberFunctionAsRawFunctionPointer() | |
{ | |
return detail::ProxyFunction<decltype(TMemFunc)>::template GetWrapped<TMemFunc, TCallConv>(); | |
} | |
} | |
using detail::CallConv; | |
using detail::WrapMemberFunctionAsRawFunctionPointer; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment