Рассмотрим следующую оболочку вокруг механизма динамического связывания Win32:
#include <boost/noncopyable.hpp>
#include <windows.h>
#include "Exception.hpp"
namespace WindowsApi
{
class RuntimeDynamicLinker : boost::noncopyable
{
HMODULE hMod_;
public:
RuntimeDynamicLinker(const wchar_t * moduleName)
{
hMod_ = LoadLibraryW(moduleName);
if (hMod_ == 0)
{
Exception::Throw(GetLastError());
}
}
template <typename T>
T GetFunction(const char* functionName)
{
FARPROC result = GetProcAddress(hMod_, functionName);
if (result == 0)
{
Exception::Throw(GetLastError());
}
return reinterpret_cast<T>(result);
}
~RuntimeDynamicLinker()
{
FreeLibrary(hMod_);
}
};
}
И пример клиента:
typedef NTSTATUS (NTAPI * NtQueryInformationProcess_t)(
IN HANDLE,
IN PROCESS_INFORMATION_CLASS,
OUT PVOID,
IN ULONG,
OUT PULONG);
RuntimeDynamicLinker ntdll(L"ntdll.dll");
NtQueryInformationProcess_t NtQueryInformationProcess =
ntdll.GetFunction<NtQueryInformationProcess_t>("NtQueryInformationProcess");
В принципе, я хотел бы добавить сообщение об ошибке, если кто-нибудьпытается использовать GetFunction
, где T
- это что-то отличное от типа указателя на функцию (потому что reinterpret_cast
, который я вынужден использовать здесь, может скрыть ошибки пользователя).
Копать черты типа наддува,Я обнаружил, что существует шаблон is_function
.Однако is_function
принимает ссылки на функции, что в моем случае было бы ошибкой пользователя (только функция указатели ).
Как изменить RuntimeDynamicLinker::GetFunction<T>()
, чтобы получить достаточно понятный компиляторсообщение об ошибке, если T
не является указателем на тип функции?
(Примечание: я никогда не делал TMP, поэтому не бойтесь переходить от «базовых» к обычным вещам).пользователи TMP)