Все в куче, уж не обессудьте.
#define FLATTEN_STR(buff, name, idx) \
(buff)[4*(idx)] = (TCHAR)((name##idx & 0xFF000000) >> 24);\
(buff)[4*(idx) + 1] = (TCHAR)((name##idx & 0xFF0000) >> 16);\
(buff)[4*(idx) + 2] = (TCHAR)((name##idx & 0xFF00) >> 8);\
(buff)[4*(idx) + 3] = (TCHAR)(name##idx & 0xFF);
void FlattenStr(LPSTR szBuffer, DWORD n0, DWORD n1, DWORD n2, DWORD n3, DWORD n4, DWORD n5, DWORD n6, DWORD n7)
{
FLATTEN_STR(szBuffer, n, 0);
FLATTEN_STR(szBuffer, n, 1);
FLATTEN_STR(szBuffer, n, 2);
FLATTEN_STR(szBuffer, n, 3);
FLATTEN_STR(szBuffer, n, 4);
FLATTEN_STR(szBuffer, n, 5);
FLATTEN_STR(szBuffer, n, 6);
FLATTEN_STR(szBuffer, n, 7);
szBuffer[64] = _T('\0');
}
template <DWORD n0 = 0, DWORD n1 = 0, DWORD n2 = 0, DWORD n3 = 0, DWORD n4 = 0, DWORD n5 = 0, DWORD n6 = 0, DWORD n7 = 0>
struct CNameId
{
enum {name_size = 65, m_n0 = n0, m_n1 = n1, m_n2 = n2, m_n3 = n3, m_n4 = n4, m_n5 = n5, m_n6 = n6, m_n7 = n7};
static void MakeStr(LPTSTR szBuffer)
{
FlattenStr(szBuffer, n0,n1,n2,n3,n4,n5,n6,n7);
}
};
template <class Name>
class CModule
{
public:
HMODULE m_hModule;
typedef CModule<Name> type;
typedef Name name_type;
static type &GetModule()
{
static type Module;
return Module;
}
~CModule()
{
if (m_hModule)
FreeLibrary(m_hModule);
}
private:
CModule()
{
TCHAR szFileName[name_type::name_size];
name_type::MakeStr(szFileName);
m_hModule = LoadLibrary(szFileName);
}
};
template <class Module, class Name, class Proxy>
class CDynFunction
{
public:
typedef CDynFunction<Module, Name, Proxy> type;
typedef Proxy proxy_type;
typedef Module module_type;
typedef Name name_type;
proxy_type::fun_type m_pfnProxy;
static type &GetProxy()
{
static type proxy;
return proxy;
}
static BOOL InitFunction()
{
HMODULE hModule = Module::GetModule().m_hModule;
if (hModule)
{
TCHAR szFunName[name_type::name_size];
name_type::MakeStr(szFunName);
FARPROC pFunction = GetProcAddress(hModule, szFunName);
if (pFunction)
{
GetProxy().m_pfnProxy = (proxy_type::fun_type)pFunction;
return TRUE;
}
}
return FALSE;
}
private:
CDynFunction():m_pfnProxy(&proxy_type::Proxy<type>::ProxyFun)
{
}
};
template<class R, R value = R()>
struct FunProxyValuePolicy
{
template <class DynFunction>
struct Dummy
{
static DynFunction::proxy_type::ret_type MakeReturn()
{
return value;
}
};
};
struct CDynFunException
{
CDynFunException();
CDynFunException(LPCTSTR sMessage):m_sMessage(sMessage)
{
}
CDynFunException(const CDynFunException &other):m_sMessage(other.m_sMessage)
{
}
CDynFunException &operator = (const CDynFunException &other)
{
m_sMessage = other.m_sMessage;
return *this;
}
CString m_sMessage;
};
template<class E = CDynFunException>
struct FunProxyThrowPolicy
{
template <class DynFunction>
struct Dummy
{
static DynFunction::proxy_type::ret_type MakeReturn()
{
TCHAR szFunName[DynFunction::name_type::name_size];
DynFunction::name_type::MakeStr(szFunName);
CString sMessage;
sMessage.Format(_T("Can'n load procedure <%s>: %d"), szFunName, GetLastError());
throw E(sMessage);
return 0;
}
};
};
template <typename R, typename P1, class Policy = FunProxyValuePolicy<R> > struct FunProxy
{
typedef R (WINAPI *fun_type)(P1);
typedef R ret_type;
template <class DynFunction> struct Proxy
{
static R WINAPI ProxyFun(P1 param)
{
if (DynFunction::InitFunction())
return DynFunction::GetProxy().m_pfnProxy(param);
return Policy::Dummy<DynFunction>::MakeReturn();
}
};
};
#define USE_MODULE_BEGIN(nmspace, NameId) \
namespace nmspace \
{\
typedef CModule< CNameId< /NameId/ > > module_type;\
#define USE_MODULE_END \
};\
#define DECLARE_FUN_P1(Name, NameId, R, P1)\
R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId< /NameId/ >, FunProxy<R, P1> >::GetProxy().m_pfnProxy;
#define DECLARE_FUN_P1_ERR(Name, NameId, R, P1, E)\
R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId< /NameId/ >, FunProxy<R, P1, FunProxyValuePolicy<R, E> > >::GetProxy().m_pfnProxy;
#define DECLARE_FUN_P1_THROW(Name, NameId, R, P1)\
R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId< /NameId/ >, FunProxy<R, P1, FunProxyThrowPolicy<> > >::GetProxy().m_pfnProxy;