Re[3]: Pure C++ delay load
__>Есть идея, но она мне кажется неосуществима.
__>Что-то такое :
__>__>#define CAT_0(x) CAT(x,0)
__>//...
__>#define CAT_n(x) CAT(x,n)
__>#define REPEAT_N(nfrom,nto,x) CAT(CAT_,nfrom)(x) /* как-нибудь перебор */ CAT(CAT_(nto))(x)
__>
А зачем это предлагается, я что то не понял.
__>Вместо _T('\0') лучше писать просто 0, меньше проблем, вдобавок макрос _T определяется в commctrl.h, а если он не будет подключен то будут проблемы.
Нет, это в tchar.h, и проблем не будет
__>Есть еще предложение убрать CString из CDynFunException, таким образом сделать так чтобы можно было использовать код в программах WinAPI.
__>__>struct CDynFunException
__>{
__> CDynFunException() : m_sMessage(0) {}
__> CDynFunException(LPCTSTR sMessage) : m_sMessage(0)
__> { SetMessage(sMessage); }
__> CDynFunException(const CDynFunException &other) : m_sMessage(0)
__> { SetMessage(other.sMessage); }
__> CDynFunException &operator = (const CDynFunException &other)
__> {
__> SetMessage(other.sMessage);
__> return *this ;
__> }
__> ~CDynFunExecption()
__> { delete [] m_sMessage; }
__> const TCHAR* GetMessage() { return m_sMessage; }
__>private :
__> void SetMessage(LPCTSTR sMessage)
__> {
__> delete [] m_sMessage;
__> m_sMessage = new TCHAR[lstrlen(other.m_sMessage)+1];
__> lstrcpy(m_sMessage,other.m_sMessage);
__> }
__> TCHAR* m_sMessage;
__>};
__>
new может сам вызывать эксепшен — начинаем тихо форматировать диск
Конечно, лучше использовать malloc\free.
__>FunProxyThrowPolicy использует тоже CString, однако он выкидывает это как исключение.
__>Поэтому пользователю придется заботиться об уничтожении выделенной памяти или же сделать обертку для этого.
Там можно вообще выделять буфер не динамически, а на стеке — максимальный размер строки с именем функции известен в FunProxyThrowPolicy::Dummy::MakeReturn через DynFunction::name_type во время компиляции, размер буфера под целое тоже. Просто лень было (да и важнее проблемы были и есть) — я политики для исключений сделал больше просто для того, дабы показать, что очень просто расширить предлагаемый функционал.
Re[4]: Pure C++ delay load
Здравствуйте, Andrew S, Вы писали:
AS>А зачем это предлагается, я что то не понял.
Да так тупая затея
__>>Вместо _T('\0') лучше писать просто 0, меньше проблем, вдобавок макрос _T определяется в commctrl.h, а если он не будет подключен то будут проблемы.
AS>Нет, это в tchar.h, и проблем не будет
Да, там тоже есть, а если он не подключен что делать ?
Так что
0 , а не _T('\0').
__>>Есть еще предложение убрать CString из CDynFunException, таким образом сделать так чтобы можно было использовать код в программах WinAPI.
__>><skip>
__>>
AS>new может сам вызывать эксепшен — начинаем тихо форматировать диск Конечно, лучше использовать malloc\free.
Проверку исключения я убрал, так как суть не в нем.
А вообще malloc подойдет конечно
Будет такое :
struct CDynFunException
{
CDynFunException() : m_sMessage(0) {}
CDynFunException(LPCTSTR sMessage) : m_sMessage(0)
{ SetMessage(sMessage); }
CDynFunException(const CDynFunException& other) : m_sMessage(0)
{ SetMessage(other.sMessage); }
CDynFunException &operator =(const CDynFunException &other)
{
SetMessage(other.sMessage);
return *this ;
}
~CDynFunExecption()
{ free(m_sMessage); }
const TCHAR* GetMessage() { return m_sMessage; }
private :
void SetMessage(LPCTSTR sMessage)
{
free(m_sMessage);
m_sMessage = malloc(lstrlen(other.m_sMessage)+1);
lstrcpy(m_sMessage,other.m_sMessage);
}
TCHAR* m_sMessage;
};
__>>FunProxyThrowPolicy использует тоже CString, однако он выкидывает это как исключение.
__>>Поэтому пользователю придется заботиться об уничтожении выделенной памяти или же сделать обертку для этого.
AS>Там можно вообще выделять буфер не динамически, а на стеке — максимальный размер строки с именем функции известен в FunProxyThrowPolicy::Dummy::MakeReturn через DynFunction::name_type во время компиляции, размер буфера под целое тоже. Просто лень было (да и важнее проблемы были и есть) — я политики для исключений сделал больше просто для того, дабы показать, что очень просто расширить предлагаемый функционал.
Ясно.
Собственно, версия 1.04
Список изменений :
Пофикшен баг с FLATTEN_STR
Изменены размножающие макросы — теперь удобнее и больше возможностей
С учетом возвращаемого типа void переработаны политика исключений и прокси вызова
В соответствии с пожеланиями телезрителей CString отправлен в dev\null, его в проекте больше нет
Немного причесан код для большего соответствия ANSI, где это возможно
To do
Компилеро-независимый способ задания строк, сейчас работает только на линейке VC
Автоматический генератор макросов DECLARE_FUN_XXX
Что то еще?
Как обычно — ждем сообщений о багах, предложений по фичам и прочее-прочее.
// delayimphlp.h: Delay import helper
// Developer: Andrew Solodovnikov
// E-mail: none
// Date: 03.08.2004
#ifndef __DELAYIMPHLP_H__
#define __DELAYIMPHLP_H__
#define DL_CAT_(x,y) x##y
#define DL_CAT(x,y) DL_CAT_(x,y)
#define MAX_DL_REPEAT 16
#define DL_COMMA() ,
#define DL_EMPTY()
// DL_REPEAT_N
#define DL_REPEAT_IMPL_N_0(x, d)
#define DL_REPEAT_IMPL_N_1(x, d) DL_CAT(x,1)
#define DL_REPEAT_IMPL_N_2(x, d) DL_REPEAT_IMPL_N_1(x, d)d() DL_CAT(x,2)
#define DL_REPEAT_IMPL_N_3(x, d) DL_REPEAT_IMPL_N_2(x, d)d() DL_CAT(x,3)
#define DL_REPEAT_IMPL_N_4(x, d) DL_REPEAT_IMPL_N_3(x, d)d() DL_CAT(x,4)
#define DL_REPEAT_IMPL_N_5(x, d) DL_REPEAT_IMPL_N_4(x, d)d() DL_CAT(x,5)
#define DL_REPEAT_IMPL_N_6(x, d) DL_REPEAT_IMPL_N_5(x, d)d() DL_CAT(x,6)
#define DL_REPEAT_IMPL_N_7(x, d) DL_REPEAT_IMPL_N_6(x, d)d() DL_CAT(x,7)
#define DL_REPEAT_IMPL_N_8(x, d) DL_REPEAT_IMPL_N_7(x, d)d() DL_CAT(x,8)
#define DL_REPEAT_IMPL_N_9(x, d) DL_REPEAT_IMPL_N_8(x, d)d() DL_CAT(x,9)
#define DL_REPEAT_IMPL_N_10(x, d) DL_REPEAT_IMPL_N_9(x, d)d() DL_CAT(x,10)
#define DL_REPEAT_IMPL_N_11(x, d) DL_REPEAT_IMPL_N_10(x, d)d() DL_CAT(x,11)
#define DL_REPEAT_IMPL_N_12(x, d) DL_REPEAT_IMPL_N_11(x, d)d() DL_CAT(x,12)
#define DL_REPEAT_IMPL_N_13(x, d) DL_REPEAT_IMPL_N_12(x, d)d() DL_CAT(x,13)
#define DL_REPEAT_IMPL_N_14(x, d) DL_REPEAT_IMPL_N_13(x, d)d() DL_CAT(x,14)
#define DL_REPEAT_IMPL_N_15(x, d) DL_REPEAT_IMPL_N_14(x, d)d() DL_CAT(x,15)
#define DL_REPEAT_IMPL_N_16(x, d) DL_REPEAT_IMPL_N_15(x, d)d() DL_CAT(x,16)
#define DL_REPEAT_IMPL_N(n, x, d) DL_CAT(DL_REPEAT_IMPL_N_,n)(x, d)
#define DL_REPEAT_N(n,x) DL_REPEAT_IMPL_N(n, x, DL_COMMA)
// DL_REPEAT_PARAM_N
#define DL_REPEAT_PARAM_IMPL_N0(n, m, d1, d2)
#define DL_REPEAT_PARAM_IMPL_N1(n, m, d1, d2) DL_CAT(n,1) DL_CAT(m,1)
#define DL_REPEAT_PARAM_IMPL_N2(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N1(n, m, d1, d2)d1() DL_CAT(n,2)d2() DL_CAT(m,2)
#define DL_REPEAT_PARAM_IMPL_N3(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N2(n, m, d1, d2)d1() DL_CAT(n,3)d2() DL_CAT(m,3)
#define DL_REPEAT_PARAM_IMPL_N4(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N3(n, m, d1, d2)d1() DL_CAT(n,4)d2() DL_CAT(m,4)
#define DL_REPEAT_PARAM_IMPL_N5(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N4(n, m, d1, d2)d1() DL_CAT(n,5)d2() DL_CAT(m,5)
#define DL_REPEAT_PARAM_IMPL_N6(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N5(n, m, d1, d2)d1() DL_CAT(n,6)d2() DL_CAT(m,6)
#define DL_REPEAT_PARAM_IMPL_N7(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N6(n, m, d1, d2)d1() DL_CAT(n,7)d2() DL_CAT(m,7)
#define DL_REPEAT_PARAM_IMPL_N8(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N7(n, m, d1, d2)d1() DL_CAT(n,8)d2() DL_CAT(m,8)
#define DL_REPEAT_PARAM_IMPL_N9(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N8(n, m, d1, d2)d1() DL_CAT(n,9)d2() DL_CAT(m,9)
#define DL_REPEAT_PARAM_IMPL_N10(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N9(n, m, d1, d2)d1() DL_CAT(n,10)d2() DL_CAT(m,10)
#define DL_REPEAT_PARAM_IMPL_N11(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N10(n, m, d1, d2)d1() DL_CAT(n,11)d2() DL_CAT(m,11)
#define DL_REPEAT_PARAM_IMPL_N12(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N11(n, m, d1, d2)d1() DL_CAT(n,12)d2() DL_CAT(m,12)
#define DL_REPEAT_PARAM_IMPL_N13(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N12(n, m, d1, d2)d1() DL_CAT(n,13)d2() DL_CAT(m,13)
#define DL_REPEAT_PARAM_IMPL_N14(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N13(n, m, d1, d2)d1() DL_CAT(n,14)d2() DL_CAT(m,14)
#define DL_REPEAT_PARAM_IMPL_N15(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N14(n, m, d1, d2)d1() DL_CAT(n,15)d2() DL_CAT(m,15)
#define DL_REPEAT_PARAM_IMPL_N16(n,m, d1, d2) DL_REPEAT_PARAM_IMPL_N15(n, m, d1, d2)d1() DL_CAT(n,16)d2() DL_CAT(m,16)
#define DL_REPEAT_PARAM_IMPL_N(c, n, m, d1, d2) DL_CAT(DL_REPEAT_PARAM_IMPL_N,c)(n, m, d1, d2)
#define DL_REPEAT_PARAM_N(c, n, m) DL_REPEAT_PARAM_IMPL_N(c, n, m, DL_COMMA, DL_EMPTY)
// DL_REPEAT_DEF_IMPL_N
#define DL_REPEAT_DEF_IMPL_N0(n, def, d)
#define DL_REPEAT_DEF_IMPL_N1(n, def, d) DL_CAT(DL_CAT(n,1), def)
#define DL_REPEAT_DEF_IMPL_N2(n, def, d) DL_REPEAT_DEF_IMPL_N1(n, def, d)d() DL_CAT(DL_CAT(n,2), def)
#define DL_REPEAT_DEF_IMPL_N3(n, def, d) DL_REPEAT_DEF_IMPL_N2(n, def, d)d() DL_CAT(DL_CAT(n,3), def)
#define DL_REPEAT_DEF_IMPL_N4(n, def, d) DL_REPEAT_DEF_IMPL_N3(n, def, d)d() DL_CAT(DL_CAT(n,4), def)
#define DL_REPEAT_DEF_IMPL_N5(n, def, d) DL_REPEAT_DEF_IMPL_N4(n, def, d)d() DL_CAT(DL_CAT(n,5), def)
#define DL_REPEAT_DEF_IMPL_N6(n, def, d) DL_REPEAT_DEF_IMPL_N5(n, def, d)d() DL_CAT(DL_CAT(n,6), def)
#define DL_REPEAT_DEF_IMPL_N7(n, def, d) DL_REPEAT_DEF_IMPL_N6(n, def, d)d() DL_CAT(DL_CAT(n,7), def)
#define DL_REPEAT_DEF_IMPL_N8(n, def, d) DL_REPEAT_DEF_IMPL_N7(n, def, d)d() DL_CAT(DL_CAT(n,8), def)
#define DL_REPEAT_DEF_IMPL_N9(n, def, d) DL_REPEAT_DEF_IMPL_N8(n, def, d)d() DL_CAT(DL_CAT(n,9), def)
#define DL_REPEAT_DEF_IMPL_N10(n, def, d) DL_REPEAT_DEF_IMPL_N9(n, def, d)d() DL_CAT(DL_CAT(n,10), def)
#define DL_REPEAT_DEF_IMPL_N11(n, def, d) DL_REPEAT_DEF_IMPL_N10(n, def, d)d() DL_CAT(DL_CAT(n,11), def)
#define DL_REPEAT_DEF_IMPL_N12(n, def, d) DL_REPEAT_DEF_IMPL_N11(n, def, d)d() DL_CAT(DL_CAT(n,12), def)
#define DL_REPEAT_DEF_IMPL_N13(n, def, d) DL_REPEAT_DEF_IMPL_N12(n, def, d)d() DL_CAT(DL_CAT(n,13), def)
#define DL_REPEAT_DEF_IMPL_N14(n, def, d) DL_REPEAT_DEF_IMPL_N13(n, def, d)d() DL_CAT(DL_CAT(n,14), def)
#define DL_REPEAT_DEF_IMPL_N15(n, def, d) DL_REPEAT_DEF_IMPL_N14(n, def, d)d() DL_CAT(DL_CAT(n,15), def)
#define DL_REPEAT_DEF_IMPL_N16(n, def, d) DL_REPEAT_DEF_IMPL_N15(n, def, d)d() DL_CAT(DL_CAT(n,16), def)
#define DL_REPEAT_DEF_IMPL_N(c, n, def, d) DL_CAT(DL_REPEAT_DEF_IMPL_N,c)(n, def, d)
#define DL_REPEAT_DEF_N(c, n, def) DL_REPEAT_DEF_IMPL_N(c, n, def, DL_COMMA)
// DL_REPEAT_MACRO_N
#define DL_REPEAT_MACRO_IMPL_N0(m, p, d)
#define DL_REPEAT_MACRO_IMPL_N1(m, p, d) m(p,1)
#define DL_REPEAT_MACRO_IMPL_N2(m, p, d) DL_REPEAT_MACRO_IMPL_N1(m, p, d)d() m(p,2)
#define DL_REPEAT_MACRO_IMPL_N3(m, p, d) DL_REPEAT_MACRO_IMPL_N2(m, p, d)d() m(p,3)
#define DL_REPEAT_MACRO_IMPL_N4(m, p, d) DL_REPEAT_MACRO_IMPL_N3(m, p, d)d() m(p,4)
#define DL_REPEAT_MACRO_IMPL_N5(m, p, d) DL_REPEAT_MACRO_IMPL_N4(m, p, d)d() m(p,5)
#define DL_REPEAT_MACRO_IMPL_N6(m, p, d) DL_REPEAT_MACRO_IMPL_N5(m, p, d)d() m(p,6)
#define DL_REPEAT_MACRO_IMPL_N7(m, p, d) DL_REPEAT_MACRO_IMPL_N6(m, p, d)d() m(p,7)
#define DL_REPEAT_MACRO_IMPL_N8(m, p, d) DL_REPEAT_MACRO_IMPL_N7(m, p, d)d() m(p,8)
#define DL_REPEAT_MACRO_IMPL_N9(m, p, d) DL_REPEAT_MACRO_IMPL_N8(m, p, d)d() m(p,9)
#define DL_REPEAT_MACRO_IMPL_N10(m, p, d) DL_REPEAT_MACRO_IMPL_N9(m, p, d)d() m(p,10)
#define DL_REPEAT_MACRO_IMPL_N11(m, p, d) DL_REPEAT_MACRO_IMPL_N10(m, p, d)d() m(p,11)
#define DL_REPEAT_MACRO_IMPL_N12(m, p, d) DL_REPEAT_MACRO_IMPL_N11(m, p, d)d() m(p,12)
#define DL_REPEAT_MACRO_IMPL_N13(m, p, d) DL_REPEAT_MACRO_IMPL_N12(m, p, d)d() m(p,13)
#define DL_REPEAT_MACRO_IMPL_N14(m, p, d) DL_REPEAT_MACRO_IMPL_N13(m, p, d)d() m(p,14)
#define DL_REPEAT_MACRO_IMPL_N15(m, p, d) DL_REPEAT_MACRO_IMPL_N14(m, p, d)d() m(p,15)
#define DL_REPEAT_MACRO_IMPL_N16(m, p, d) DL_REPEAT_MACRO_IMPL_N15(m, p, d)d() m(p,16)
#define DL_REPEAT_MACRO_IMPL_N(c, m, p, d) DL_CAT(DL_REPEAT_MACRO_IMPL_N,c)(m,p, d)
#define DL_REPEAT_MACRO_N(c, m, p) DL_REPEAT_MACRO_IMPL_N(c, m, p, DL_COMMA)
#define FLATTEN_STR3(val) (((val) > 0xFFFFFF) ? (val) : 0)
#define FLATTEN_STR2(val) (((val) > 0xFFFFFF) ? (val) : FLATTEN_STR3(val << 8))
#define FLATTEN_STR1(val) (((val) > 0xFFFFFF) ? (val) : FLATTEN_STR2(val << 8))
#define FLATTEN_STR0(val) (((val) > 0xFFFFFF) ? (val) : FLATTEN_STR1(val << 8))
#define FLATTEN_STR_(val) \
(TCHAR)HIBYTE(HIWORD(val)), (TCHAR)LOBYTE(HIWORD(val)), (TCHAR)HIBYTE(LOWORD(val)), (TCHAR)LOBYTE(LOWORD(val))
#define FLATTEN_STR(val, num) FLATTEN_STR_(FLATTEN_STR0(DL_CAT(val, num)))
#pragma warning (disable: 4786)
template <int count>
struct CNameIdHolder
{
template <DL_REPEAT_N(MAX_DL_REPEAT, DWORD n)>
struct CNameIdHolderImpl
{
static LPCTSTR GetStr()
{
static const TCHAR szBuffer[] = {
DL_REPEAT_MACRO_N(MAX_DL_REPEAT, FLATTEN_STR, n),
_T('\0' )
};
return szBuffer;
}
};
};
#define NAME_ID_HOLDER_SPEC(num)\
template <>\
struct CNameIdHolder<num>\
{\
template <DL_REPEAT_N(MAX_DL_REPEAT, DWORD n)>\
struct CNameIdHolderImpl\
{\
static LPCTSTR GetStr()\
{\
static const TCHAR szBuffer[] = {\
DL_REPEAT_MACRO_N(num, FLATTEN_STR, n),\
_T('\0' )\
};\
return szBuffer;\
}\
};\
};
NAME_ID_HOLDER_SPEC(15)
NAME_ID_HOLDER_SPEC(14)
NAME_ID_HOLDER_SPEC(13)
NAME_ID_HOLDER_SPEC(12)
NAME_ID_HOLDER_SPEC(11)
NAME_ID_HOLDER_SPEC(10)
NAME_ID_HOLDER_SPEC(9)
NAME_ID_HOLDER_SPEC(8)
NAME_ID_HOLDER_SPEC(7)
NAME_ID_HOLDER_SPEC(6)
NAME_ID_HOLDER_SPEC(5)
NAME_ID_HOLDER_SPEC(4)
NAME_ID_HOLDER_SPEC(3)
NAME_ID_HOLDER_SPEC(2)
NAME_ID_HOLDER_SPEC(1)
template <>
struct CNameIdHolder<0>
{
template <DL_REPEAT_N(MAX_DL_REPEAT, DWORD n)>
struct CNameIdHolderImpl
{
static LPCTSTR GetStr()
{
return NULL;
}
};
};
#define NN_REP_COUNT_M(p, n) (!DL_CAT(p,n)) ? (n-1):
template <DL_REPEAT_DEF_N(MAX_DL_REPEAT, DWORD n, = 0)>
struct CNameId
{
enum
{
DL_REPEAT_PARAM_N(MAX_DL_REPEAT, m_n, =n),
count = DL_REPEAT_MACRO_IMPL_N(MAX_DL_REPEAT, NN_REP_COUNT_M, n, DL_EMPTY) MAX_DL_REPEAT,
length = count * sizeof (DWORD)
};
static LPCTSTR GetStr()
{
return CNameIdHolder<count>::template CNameIdHolderImpl<DL_REPEAT_N(MAX_DL_REPEAT, n)>::GetStr();
}
};
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()
{
m_hModule = LoadLibrary(name_type::GetStr());
}
};
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;
static proxy_type::fun_type &GetProxy()
{
static proxy_type::fun_type proxy = proxy_type::template Proxy<type>::ProxyFun;
return proxy;
}
static BOOL InitFunction()
{
HMODULE hModule = Module::GetModule().m_hModule;
if (hModule)
{
FARPROC pFunction = GetProcAddress(hModule, name_type::GetStr());
if (pFunction)
{
GetProxy() = (proxy_type::fun_type)pFunction;
return TRUE;
}
}
return FALSE;
}
};
struct CDynFunException
{
CDynFunException(): m_sMessage(NULL)
{
};
~CDynFunException()
{
free(m_sMessage);
};
CDynFunException(LPCTSTR sMessage):m_sMessage(NULL)
{
SetMessage(sMessage);
}
CDynFunException(const CDynFunException &other):m_sMessage(NULL)
{
SetMessage(other.m_sMessage);
}
CDynFunException &operator = (const CDynFunException &other)
{
SetMessage(other.m_sMessage);
return *this ;
}
void SetMessage(LPCTSTR sMessage)
{
free(m_sMessage);
m_sMessage = (LPTSTR)malloc((_tcslen(sMessage) + 1) * sizeof (TCHAR));
if (m_sMessage)
_tcscpy(m_sMessage, sMessage);
}
LPTSTR m_sMessage;
};
template <class R> struct FunProxyThrowRetTypeTrait
{
template <class F>
struct FunctionTraitImpl
{
static R MakeReturn()
{
F::MakeReturnImpl();
return R();
}
};
};
template <> struct FunProxyThrowRetTypeTrait<void >
{
template <class F>
struct FunctionTraitImpl
{
static void MakeReturn()
{
F::MakeReturnImpl();
}
};
};
template <class E = CDynFunException>
struct FunProxyThrowPolicy
{
template <class DynFunction>
struct FunctionTrait:public FunProxyThrowRetTypeTrait<DynFunction::proxy_type::ret_type>::template FunctionTraitImpl<FunctionTrait<DynFunction> >
{
static void MakeReturnImpl()
{
TCHAR szMessage[DynFunction::name_type::length + 64];
_stprintf(szMessage, _T("Can'n resolve procedure <%s>: %d" ), DynFunction::name_type::GetStr(), GetLastError());
throw E(szMessage);
}
};
};
// we need not implement void return type value policy,
// coz void function can only throw on error
template <class R, R value = R()>
struct FunProxyValuePolicy
{
template <class DynFunction>
struct FunctionTrait
{
static DynFunction::proxy_type::ret_type MakeReturn()
{
return value;
}
};
};
#define FUN_PROXY(n) DL_CAT(FunProxy,n)
#define FUN_PROXY_IMPL(n) DL_CAT(FUN_PROXY(n),Impl)
#define DECLARE_FUN_PROXY(param_count) \
template <typename R> struct FUN_PROXY_IMPL(param_count)\
{\
template <class DynFunction, DL_REPEAT_N(param_count, typename P), class Policy> struct RetProxy\
{\
static R WINAPI ProxyFun(DL_REPEAT_PARAM_N(param_count, P, v))\
{\
if (DynFunction::InitFunction())\
return DynFunction::GetProxy()(DL_REPEAT_N(param_count, v));\
return Policy::template FunctionTrait<DynFunction>::MakeReturn();\
}\
};\
};\
\
template <> struct FUN_PROXY_IMPL(param_count) <void >\
{\
template <class DynFunction, DL_REPEAT_N(param_count, typename P), class Policy> struct RetProxy\
{\
static R WINAPI ProxyFun(DL_REPEAT_PARAM_N(param_count, P, v))\
{\
if (DynFunction::InitFunction())\
DynFunction::GetProxy()(DL_REPEAT_N(param_count, v));\
else \
Policy::template FunctionTrait<DynFunction>::MakeReturn();\
}\
};\
};\
\
template <typename R, DL_REPEAT_N(param_count, typename P), class Policy = FunProxyValuePolicy<R> > struct FUN_PROXY(param_count)\
{\
typedef R (WINAPI *fun_type)(DL_REPEAT_N(param_count, P));\
typedef R ret_type;\
template <class DynFunction> struct Proxy:public FUN_PROXY_IMPL(param_count)<R>::template RetProxy<DynFunction, DL_REPEAT_N(param_count, P), Policy>\
{\
};\
};
DECLARE_FUN_PROXY(1)
DECLARE_FUN_PROXY(2)
DECLARE_FUN_PROXY(3)
DECLARE_FUN_PROXY(4)
DECLARE_FUN_PROXY(5)
DECLARE_FUN_PROXY(6)
DECLARE_FUN_PROXY(7)
DECLARE_FUN_PROXY(8)
DECLARE_FUN_PROXY(9)
DECLARE_FUN_PROXY(10)
DECLARE_FUN_PROXY(11)
DECLARE_FUN_PROXY(12)
DECLARE_FUN_PROXY(13)
DECLARE_FUN_PROXY(14)
DECLARE_FUN_PROXY(15)
DECLARE_FUN_PROXY(16)
// usefull macro's
#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) \
static R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId< /NameId/ >, FUN_PROXY(1)<R, P1> >::GetProxy();
#define DECLARE_FUN_P1_ERR(Name, NameId, R, P1, E)\
static R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId< /NameId/ >, FUN_PROXY(1)<R, P1, FunProxyValuePolicy<R,E> > >::GetProxy();
#define DECLARE_FUN_P1_THROW(Name, NameId, R, P1)\
static R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId< /NameId/ >, FUN_PROXY(1)<R, P1, FunProxyThrowPolicy<> > >::GetProxy();
#endif
Здравствуйте, Andrew S, Вы писали:
AS>Собственно, версия 1.04
AS>Список изменений :
AS>
AS>В соответствии с пожеланиями телезрителей CString отправлен в dev/ null, его в проекте больше нет
AS>
Наверное все же стоит в структуре CDynFunException член m_sMessage сделать приватным, мало ли что будет
__>Наверное все же стоит в структуре CDynFunException член m_sMessage сделать приватным, мало ли что будет
Done. Впрочем, когда выбрасывается исключение, то мало уже не будет
Здравствуйте, Andrew S, Вы писали:
AS>
AS>Компилеро-независимый способ задания строк, сейчас работает только на линейке VC
AS>Автоматический генератор макросов DECLARE_FUN_XXX
AS>Что то еще?
AS>
Компиляторонезависимый будет так : (при потере функциональности
)
#define DECLARE_FUN1_P1(Name, NameId0, R, P1) \
static R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId<NameId0>, FUN_PROXY(1)<R, P1> >::GetProxy();
#define DECLARE_FUN2_P1(Name, NameId0, NameId1, R, P1) \
static R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId<NameId0,NameId1>, FUN_PROXY(1)<R, P1> >::GetProxy();
//...
Или же так:
#define DECLARE_FUN1_P1(Name, NameId0, R, P1) \
static R (WINAPI *&Name)(REPEAT_N(1,P)) = CDynFunction<module_type, CNameId<REPEAT_N(0,NameId)>, FUN_PROXY(1)<R, REPEAT_N(1,P)> >::GetProxy();
#define DECLARE_FUN2_P1(Name, NameId0, NameId1, R, P1) \
static R (WINAPI *&Name)(REPEAT_N(1,P)) = CDynFunction<module_type, CNameId<REPEAT_N(1,NameId)>, FUN_PROXY(1)<R, REPEAT_N(1,P)> >::GetProxy();
//...
Идея думаю ясна.
Есть идея, только не знаю если она переносима :
Если написать #define X(a0,a1,a2....an), по при использовании X(a) в a1, a2 будет пусто.
Это на VC++, если на других компиляторах также то проблем нет.
>>Компилеро-независимый способ задания строк, сейчас работает только на линейке VC
По следам буста изменил способ задания строк. Теперь декларации выглядят так:
USE_MODULE_BEGIN(kernel, (kern)(el32)(.dll))
DECLARE_FUN_P1(GetModuleHandle, (GetM)(odul)(eHan)(dleA), HMODULE, LPCTSTR)
DECLARE_FUN_P1(GetModuleHandleW, (GetM)(odul)(eHan)(dleW), HMODULE, LPCWSTR)
DECLARE_FUN_P1_THROW(InitializeCriticalSection, (Init)(iali)(zeCr)(itic)(alSe)(ctio)(n),VOID, LPCRITICAL_SECTION)
USE_MODULE_END
Уже лучше, конечно, но и не идеально, конечно.
Собственно, можно вообще сделать декларации в виде
USE_MODULE_BEGIN(kernel, (kern)(el32)(.dll))
DECLARE_FUN_P1((GetM)(odul)(eHan)(dleA), HMODULE, LPCTSTR)
DECLARE_FUN_P1((GetM)(odul)(eHan)(dleW), HMODULE, LPCWSTR)
DECLARE_FUN_P1_THROW(InitializeCriticalSection, (Init)(iali)(zeCr)(itic)(alSe)(ctio)(n),VOID, LPCRITICAL_SECTION)
USE_MODULE_END
Но в этом случае непонятно, как быть с юникодом... А хотя, есть мысль — ведь если в этом случае писать kernel::GetModuleHandle, то препроцессор это на основе стандартных хидеров фактически сам преобразует в нужный вариант — либо kernel::GetModuleHandleA, либо kernel::GetModuleHandleW. Фактически бесплатная поддержка юникода. Как господам такая мысль? Если понравится, сделаем так. В результате плюсы — сокращенная запись + полуавтоматический юникод.
Да, из todo остается:
>>Автоматический генератор макросов DECLARE_FUN_XXX
Есть мысли?
// delayimphlp.h: Delay import helper
// Developer: Andrew Solodovnikov
// E-mail: none
// Date: 03.08.2004
#ifndef __DELAYIMPHLP_H__
#define __DELAYIMPHLP_H__
#define DL_CAT_(x,y) x##y
#define DL_CAT(x,y) DL_CAT_(x,y)
#define MAX_DL_REPEAT 16
#define DL_COMMA() ,
#define DL_EMPTY()
// DL_REPEAT_N
#define DL_REPEAT_IMPL_N_0(x, d)
#define DL_REPEAT_IMPL_N_1(x, d) DL_CAT(x,1)
#define DL_REPEAT_IMPL_N_2(x, d) DL_REPEAT_IMPL_N_1(x, d)d() DL_CAT(x,2)
#define DL_REPEAT_IMPL_N_3(x, d) DL_REPEAT_IMPL_N_2(x, d)d() DL_CAT(x,3)
#define DL_REPEAT_IMPL_N_4(x, d) DL_REPEAT_IMPL_N_3(x, d)d() DL_CAT(x,4)
#define DL_REPEAT_IMPL_N_5(x, d) DL_REPEAT_IMPL_N_4(x, d)d() DL_CAT(x,5)
#define DL_REPEAT_IMPL_N_6(x, d) DL_REPEAT_IMPL_N_5(x, d)d() DL_CAT(x,6)
#define DL_REPEAT_IMPL_N_7(x, d) DL_REPEAT_IMPL_N_6(x, d)d() DL_CAT(x,7)
#define DL_REPEAT_IMPL_N_8(x, d) DL_REPEAT_IMPL_N_7(x, d)d() DL_CAT(x,8)
#define DL_REPEAT_IMPL_N_9(x, d) DL_REPEAT_IMPL_N_8(x, d)d() DL_CAT(x,9)
#define DL_REPEAT_IMPL_N_10(x, d) DL_REPEAT_IMPL_N_9(x, d)d() DL_CAT(x,10)
#define DL_REPEAT_IMPL_N_11(x, d) DL_REPEAT_IMPL_N_10(x, d)d() DL_CAT(x,11)
#define DL_REPEAT_IMPL_N_12(x, d) DL_REPEAT_IMPL_N_11(x, d)d() DL_CAT(x,12)
#define DL_REPEAT_IMPL_N_13(x, d) DL_REPEAT_IMPL_N_12(x, d)d() DL_CAT(x,13)
#define DL_REPEAT_IMPL_N_14(x, d) DL_REPEAT_IMPL_N_13(x, d)d() DL_CAT(x,14)
#define DL_REPEAT_IMPL_N_15(x, d) DL_REPEAT_IMPL_N_14(x, d)d() DL_CAT(x,15)
#define DL_REPEAT_IMPL_N_16(x, d) DL_REPEAT_IMPL_N_15(x, d)d() DL_CAT(x,16)
#define DL_REPEAT_IMPL_N(n, x, d) DL_CAT(DL_REPEAT_IMPL_N_,n)(x, d)
#define DL_REPEAT_N(n,x) DL_REPEAT_IMPL_N(n, x, DL_COMMA)
// DL_REPEAT_PARAM_N
#define DL_REPEAT_PARAM_IMPL_N0(n, m, d1, d2)
#define DL_REPEAT_PARAM_IMPL_N1(n, m, d1, d2) DL_CAT(n,1) DL_CAT(m,1)
#define DL_REPEAT_PARAM_IMPL_N2(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N1(n, m, d1, d2)d1() DL_CAT(n,2)d2() DL_CAT(m,2)
#define DL_REPEAT_PARAM_IMPL_N3(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N2(n, m, d1, d2)d1() DL_CAT(n,3)d2() DL_CAT(m,3)
#define DL_REPEAT_PARAM_IMPL_N4(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N3(n, m, d1, d2)d1() DL_CAT(n,4)d2() DL_CAT(m,4)
#define DL_REPEAT_PARAM_IMPL_N5(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N4(n, m, d1, d2)d1() DL_CAT(n,5)d2() DL_CAT(m,5)
#define DL_REPEAT_PARAM_IMPL_N6(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N5(n, m, d1, d2)d1() DL_CAT(n,6)d2() DL_CAT(m,6)
#define DL_REPEAT_PARAM_IMPL_N7(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N6(n, m, d1, d2)d1() DL_CAT(n,7)d2() DL_CAT(m,7)
#define DL_REPEAT_PARAM_IMPL_N8(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N7(n, m, d1, d2)d1() DL_CAT(n,8)d2() DL_CAT(m,8)
#define DL_REPEAT_PARAM_IMPL_N9(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N8(n, m, d1, d2)d1() DL_CAT(n,9)d2() DL_CAT(m,9)
#define DL_REPEAT_PARAM_IMPL_N10(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N9(n, m, d1, d2)d1() DL_CAT(n,10)d2() DL_CAT(m,10)
#define DL_REPEAT_PARAM_IMPL_N11(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N10(n, m, d1, d2)d1() DL_CAT(n,11)d2() DL_CAT(m,11)
#define DL_REPEAT_PARAM_IMPL_N12(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N11(n, m, d1, d2)d1() DL_CAT(n,12)d2() DL_CAT(m,12)
#define DL_REPEAT_PARAM_IMPL_N13(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N12(n, m, d1, d2)d1() DL_CAT(n,13)d2() DL_CAT(m,13)
#define DL_REPEAT_PARAM_IMPL_N14(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N13(n, m, d1, d2)d1() DL_CAT(n,14)d2() DL_CAT(m,14)
#define DL_REPEAT_PARAM_IMPL_N15(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N14(n, m, d1, d2)d1() DL_CAT(n,15)d2() DL_CAT(m,15)
#define DL_REPEAT_PARAM_IMPL_N16(n,m, d1, d2) DL_REPEAT_PARAM_IMPL_N15(n, m, d1, d2)d1() DL_CAT(n,16)d2() DL_CAT(m,16)
#define DL_REPEAT_PARAM_IMPL_N(c, n, m, d1, d2) DL_CAT(DL_REPEAT_PARAM_IMPL_N,c)(n, m, d1, d2)
#define DL_REPEAT_PARAM_N(c, n, m) DL_REPEAT_PARAM_IMPL_N(c, n, m, DL_COMMA, DL_EMPTY)
// DL_REPEAT_DEF_IMPL_N
#define DL_REPEAT_DEF_IMPL_N0(n, def, d)
#define DL_REPEAT_DEF_IMPL_N1(n, def, d) DL_CAT(DL_CAT(n,1), def)
#define DL_REPEAT_DEF_IMPL_N2(n, def, d) DL_REPEAT_DEF_IMPL_N1(n, def, d)d() DL_CAT(DL_CAT(n,2), def)
#define DL_REPEAT_DEF_IMPL_N3(n, def, d) DL_REPEAT_DEF_IMPL_N2(n, def, d)d() DL_CAT(DL_CAT(n,3), def)
#define DL_REPEAT_DEF_IMPL_N4(n, def, d) DL_REPEAT_DEF_IMPL_N3(n, def, d)d() DL_CAT(DL_CAT(n,4), def)
#define DL_REPEAT_DEF_IMPL_N5(n, def, d) DL_REPEAT_DEF_IMPL_N4(n, def, d)d() DL_CAT(DL_CAT(n,5), def)
#define DL_REPEAT_DEF_IMPL_N6(n, def, d) DL_REPEAT_DEF_IMPL_N5(n, def, d)d() DL_CAT(DL_CAT(n,6), def)
#define DL_REPEAT_DEF_IMPL_N7(n, def, d) DL_REPEAT_DEF_IMPL_N6(n, def, d)d() DL_CAT(DL_CAT(n,7), def)
#define DL_REPEAT_DEF_IMPL_N8(n, def, d) DL_REPEAT_DEF_IMPL_N7(n, def, d)d() DL_CAT(DL_CAT(n,8), def)
#define DL_REPEAT_DEF_IMPL_N9(n, def, d) DL_REPEAT_DEF_IMPL_N8(n, def, d)d() DL_CAT(DL_CAT(n,9), def)
#define DL_REPEAT_DEF_IMPL_N10(n, def, d) DL_REPEAT_DEF_IMPL_N9(n, def, d)d() DL_CAT(DL_CAT(n,10), def)
#define DL_REPEAT_DEF_IMPL_N11(n, def, d) DL_REPEAT_DEF_IMPL_N10(n, def, d)d() DL_CAT(DL_CAT(n,11), def)
#define DL_REPEAT_DEF_IMPL_N12(n, def, d) DL_REPEAT_DEF_IMPL_N11(n, def, d)d() DL_CAT(DL_CAT(n,12), def)
#define DL_REPEAT_DEF_IMPL_N13(n, def, d) DL_REPEAT_DEF_IMPL_N12(n, def, d)d() DL_CAT(DL_CAT(n,13), def)
#define DL_REPEAT_DEF_IMPL_N14(n, def, d) DL_REPEAT_DEF_IMPL_N13(n, def, d)d() DL_CAT(DL_CAT(n,14), def)
#define DL_REPEAT_DEF_IMPL_N15(n, def, d) DL_REPEAT_DEF_IMPL_N14(n, def, d)d() DL_CAT(DL_CAT(n,15), def)
#define DL_REPEAT_DEF_IMPL_N16(n, def, d) DL_REPEAT_DEF_IMPL_N15(n, def, d)d() DL_CAT(DL_CAT(n,16), def)
#define DL_REPEAT_DEF_IMPL_N(c, n, def, d) DL_CAT(DL_REPEAT_DEF_IMPL_N,c)(n, def, d)
#define DL_REPEAT_DEF_N(c, n, def) DL_REPEAT_DEF_IMPL_N(c, n, def, DL_COMMA)
// DL_REPEAT_MACRO_N
#define DL_REPEAT_MACRO_IMPL_N0(m, p, d)
#define DL_REPEAT_MACRO_IMPL_N1(m, p, d) m(p,1)
#define DL_REPEAT_MACRO_IMPL_N2(m, p, d) DL_REPEAT_MACRO_IMPL_N1(m, p, d)d() m(p,2)
#define DL_REPEAT_MACRO_IMPL_N3(m, p, d) DL_REPEAT_MACRO_IMPL_N2(m, p, d)d() m(p,3)
#define DL_REPEAT_MACRO_IMPL_N4(m, p, d) DL_REPEAT_MACRO_IMPL_N3(m, p, d)d() m(p,4)
#define DL_REPEAT_MACRO_IMPL_N5(m, p, d) DL_REPEAT_MACRO_IMPL_N4(m, p, d)d() m(p,5)
#define DL_REPEAT_MACRO_IMPL_N6(m, p, d) DL_REPEAT_MACRO_IMPL_N5(m, p, d)d() m(p,6)
#define DL_REPEAT_MACRO_IMPL_N7(m, p, d) DL_REPEAT_MACRO_IMPL_N6(m, p, d)d() m(p,7)
#define DL_REPEAT_MACRO_IMPL_N8(m, p, d) DL_REPEAT_MACRO_IMPL_N7(m, p, d)d() m(p,8)
#define DL_REPEAT_MACRO_IMPL_N9(m, p, d) DL_REPEAT_MACRO_IMPL_N8(m, p, d)d() m(p,9)
#define DL_REPEAT_MACRO_IMPL_N10(m, p, d) DL_REPEAT_MACRO_IMPL_N9(m, p, d)d() m(p,10)
#define DL_REPEAT_MACRO_IMPL_N11(m, p, d) DL_REPEAT_MACRO_IMPL_N10(m, p, d)d() m(p,11)
#define DL_REPEAT_MACRO_IMPL_N12(m, p, d) DL_REPEAT_MACRO_IMPL_N11(m, p, d)d() m(p,12)
#define DL_REPEAT_MACRO_IMPL_N13(m, p, d) DL_REPEAT_MACRO_IMPL_N12(m, p, d)d() m(p,13)
#define DL_REPEAT_MACRO_IMPL_N14(m, p, d) DL_REPEAT_MACRO_IMPL_N13(m, p, d)d() m(p,14)
#define DL_REPEAT_MACRO_IMPL_N15(m, p, d) DL_REPEAT_MACRO_IMPL_N14(m, p, d)d() m(p,15)
#define DL_REPEAT_MACRO_IMPL_N16(m, p, d) DL_REPEAT_MACRO_IMPL_N15(m, p, d)d() m(p,16)
#define DL_REPEAT_MACRO_IMPL_N(c, m, p, d) DL_CAT(DL_REPEAT_MACRO_IMPL_N,c)(m,p, d)
#define DL_REPEAT_MACRO_N(c, m, p) DL_REPEAT_MACRO_IMPL_N(c, m, p, DL_COMMA)
#define DL_SEQ_SIZE(seq) DL_SEQ_SIZE_IMPL(seq)
#define DL_SEQ_SIZE_IMPL(seq) DL_CAT(DL_N_, DL_SEQ_SIZE_0 seq)
#define DL_SEQ_SIZE_0(_) DL_SEQ_SIZE_1
#define DL_SEQ_SIZE_1(_) DL_SEQ_SIZE_2
#define DL_SEQ_SIZE_2(_) DL_SEQ_SIZE_3
#define DL_SEQ_SIZE_3(_) DL_SEQ_SIZE_4
#define DL_SEQ_SIZE_4(_) DL_SEQ_SIZE_5
#define DL_SEQ_SIZE_5(_) DL_SEQ_SIZE_6
#define DL_SEQ_SIZE_6(_) DL_SEQ_SIZE_7
#define DL_SEQ_SIZE_7(_) DL_SEQ_SIZE_8
#define DL_SEQ_SIZE_8(_) DL_SEQ_SIZE_9
#define DL_SEQ_SIZE_9(_) DL_SEQ_SIZE_10
#define DL_SEQ_SIZE_10(_) DL_SEQ_SIZE_11
#define DL_SEQ_SIZE_11(_) DL_SEQ_SIZE_12
#define DL_SEQ_SIZE_12(_) DL_SEQ_SIZE_13
#define DL_SEQ_SIZE_13(_) DL_SEQ_SIZE_14
#define DL_SEQ_SIZE_14(_) DL_SEQ_SIZE_15
#define DL_SEQ_SIZE_15(_) DL_SEQ_SIZE_16
#define DL_N_DL_SEQ_SIZE_0 0
#define DL_N_DL_SEQ_SIZE_1 1
#define DL_N_DL_SEQ_SIZE_2 2
#define DL_N_DL_SEQ_SIZE_3 3
#define DL_N_DL_SEQ_SIZE_4 4
#define DL_N_DL_SEQ_SIZE_5 5
#define DL_N_DL_SEQ_SIZE_6 6
#define DL_N_DL_SEQ_SIZE_7 7
#define DL_N_DL_SEQ_SIZE_8 8
#define DL_N_DL_SEQ_SIZE_9 9
#define DL_N_DL_SEQ_SIZE_10 10
#define DL_N_DL_SEQ_SIZE_11 11
#define DL_N_DL_SEQ_SIZE_12 12
#define DL_N_DL_SEQ_SIZE_13 13
#define DL_N_DL_SEQ_SIZE_14 14
#define DL_N_DL_SEQ_SIZE_15 15
#define DL_N_DL_SEQ_SIZE_16 16
#define DL_SEQ_ENUM(seq) DL_SEQ_ENUM_IMPL(seq)
#define DL_SEQ_ENUM_IMPL(seq) DL_CAT(DL_SEQ_ENUM_, DL_SEQ_SIZE(seq)) seq
#define DL_MAKE_CHAR_(x) #@x
#define DL_MAKE_CHAR(x) DL_MAKE_CHAR_(x)
#define DL_SEQ_ENUM_1(x) DL_MAKE_CHAR(x)
#define DL_SEQ_ENUM_2(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_1
#define DL_SEQ_ENUM_3(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_2
#define DL_SEQ_ENUM_4(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_3
#define DL_SEQ_ENUM_5(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_4
#define DL_SEQ_ENUM_6(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_5
#define DL_SEQ_ENUM_7(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_6
#define DL_SEQ_ENUM_8(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_7
#define DL_SEQ_ENUM_9(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_8
#define DL_SEQ_ENUM_10(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_9
#define DL_SEQ_ENUM_11(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_10
#define DL_SEQ_ENUM_12(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_11
#define DL_SEQ_ENUM_13(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_12
#define DL_SEQ_ENUM_14(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_13
#define DL_SEQ_ENUM_15(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_14
#define DL_SEQ_ENUM_16(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_15
#define FLATTEN_STR3(val) (((val) > 0xFFFFFF) ? (val) : 0)
#define FLATTEN_STR2(val) (((val) > 0xFFFFFF) ? (val) : FLATTEN_STR3(val << 8))
#define FLATTEN_STR1(val) (((val) > 0xFFFFFF) ? (val) : FLATTEN_STR2(val << 8))
#define FLATTEN_STR0(val) (((val) > 0xFFFFFF) ? (val) : FLATTEN_STR1(val << 8))
#define FLATTEN_STR_(val) \
(TCHAR)HIBYTE(HIWORD(val)), (TCHAR)LOBYTE(HIWORD(val)), (TCHAR)HIBYTE(LOWORD(val)), (TCHAR)LOBYTE(LOWORD(val))
#define FLATTEN_STR(val, num) FLATTEN_STR_(FLATTEN_STR0(DL_CAT(val, num)))
#pragma warning (disable: 4786)
template <int count>
struct CNameIdHolder
{
template <DL_REPEAT_N(MAX_DL_REPEAT, DWORD n)>
struct CNameIdHolderImpl
{
static LPCTSTR GetStr()
{
static const TCHAR szBuffer[] = {
DL_REPEAT_MACRO_N(MAX_DL_REPEAT, FLATTEN_STR, n),
_T('\0' )
};
return szBuffer;
}
};
};
#define NAME_ID_HOLDER_SPEC(num)\
template <>\
struct CNameIdHolder<num>\
{\
template <DL_REPEAT_N(MAX_DL_REPEAT, DWORD n)>\
struct CNameIdHolderImpl\
{\
static LPCTSTR GetStr()\
{\
static const TCHAR szBuffer[] = {\
DL_REPEAT_MACRO_N(num, FLATTEN_STR, n),\
_T('\0' )\
};\
return szBuffer;\
}\
};\
};
NAME_ID_HOLDER_SPEC(15)
NAME_ID_HOLDER_SPEC(14)
NAME_ID_HOLDER_SPEC(13)
NAME_ID_HOLDER_SPEC(12)
NAME_ID_HOLDER_SPEC(11)
NAME_ID_HOLDER_SPEC(10)
NAME_ID_HOLDER_SPEC(9)
NAME_ID_HOLDER_SPEC(8)
NAME_ID_HOLDER_SPEC(7)
NAME_ID_HOLDER_SPEC(6)
NAME_ID_HOLDER_SPEC(5)
NAME_ID_HOLDER_SPEC(4)
NAME_ID_HOLDER_SPEC(3)
NAME_ID_HOLDER_SPEC(2)
NAME_ID_HOLDER_SPEC(1)
template <>
struct CNameIdHolder<0>
{
template <DL_REPEAT_N(MAX_DL_REPEAT, DWORD n)>
struct CNameIdHolderImpl
{
static LPCTSTR GetStr()
{
return NULL;
}
};
};
#define NN_REP_COUNT_M(p, n) (!DL_CAT(p,n)) ? (n-1):
template <DL_REPEAT_DEF_N(MAX_DL_REPEAT, DWORD n, = 0)>
struct CNameId
{
enum
{
DL_REPEAT_PARAM_N(MAX_DL_REPEAT, m_n, =n),
count = DL_REPEAT_MACRO_IMPL_N(MAX_DL_REPEAT, NN_REP_COUNT_M, n, DL_EMPTY) MAX_DL_REPEAT,
length = count * sizeof (DWORD)
};
static LPCTSTR GetStr()
{
return CNameIdHolder<count>::template CNameIdHolderImpl<DL_REPEAT_N(MAX_DL_REPEAT, n)>::GetStr();
}
};
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()
{
m_hModule = LoadLibrary(name_type::GetStr());
}
};
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;
static proxy_type::fun_type &GetProxy()
{
static proxy_type::fun_type proxy = proxy_type::template Proxy<type>::ProxyFun;
return proxy;
}
static BOOL InitFunction()
{
HMODULE hModule = Module::GetModule().m_hModule;
if (hModule)
{
FARPROC pFunction = GetProcAddress(hModule, name_type::GetStr());
if (pFunction)
{
GetProxy() = (proxy_type::fun_type)pFunction;
return TRUE;
}
}
return FALSE;
}
};
struct CDynFunException
{
CDynFunException(): m_sMessage(NULL)
{
};
~CDynFunException()
{
free(m_sMessage);
};
CDynFunException(LPCTSTR sMessage):m_sMessage(NULL)
{
SetMessage(sMessage);
}
CDynFunException(const CDynFunException &other):m_sMessage(NULL)
{
SetMessage(other.m_sMessage);
}
CDynFunException &operator = (const CDynFunException &other)
{
SetMessage(other.m_sMessage);
return *this ;
}
void SetMessage(LPCTSTR sMessage)
{
free(m_sMessage);
m_sMessage = (LPTSTR)malloc((_tcslen(sMessage) + 1) * sizeof (TCHAR));
if (m_sMessage)
_tcscpy(m_sMessage, sMessage);
}
LPCTSTR GetMessage() const
{
return m_sMessage;
}
private :
LPTSTR m_sMessage;
};
template <class R> struct FunProxyThrowRetTypeTrait
{
template <class F>
struct FunctionTraitImpl
{
static R MakeReturn()
{
F::MakeReturnImpl();
return R();
}
};
};
template <> struct FunProxyThrowRetTypeTrait<void >
{
template <class F>
struct FunctionTraitImpl
{
static void MakeReturn()
{
F::MakeReturnImpl();
}
};
};
template <class E = CDynFunException>
struct FunProxyThrowPolicy
{
template <class DynFunction>
struct FunctionTrait:public FunProxyThrowRetTypeTrait<DynFunction::proxy_type::ret_type>::template FunctionTraitImpl<FunctionTrait<DynFunction> >
{
static void MakeReturnImpl()
{
TCHAR szMessage[DynFunction::name_type::length + 64];
_stprintf(szMessage, _T("Can'n resolve procedure <%s>: %d" ), DynFunction::name_type::GetStr(), GetLastError());
throw E(szMessage);
}
};
};
// we need not implement void return type value policy,
// coz void function can only throw on error
template <class R, R value = R()>
struct FunProxyValuePolicy
{
template <class DynFunction>
struct FunctionTrait
{
static DynFunction::proxy_type::ret_type MakeReturn()
{
return value;
}
};
};
#define FUN_PROXY(n) DL_CAT(FunProxy,n)
#define FUN_PROXY_IMPL(n) DL_CAT(FUN_PROXY(n),Impl)
#define DECLARE_FUN_PROXY(param_count) \
template <typename R> struct FUN_PROXY_IMPL(param_count)\
{\
template <class DynFunction, DL_REPEAT_N(param_count, typename P), class Policy> struct RetProxy\
{\
static R WINAPI ProxyFun(DL_REPEAT_PARAM_N(param_count, P, v))\
{\
if (DynFunction::InitFunction())\
return DynFunction::GetProxy()(DL_REPEAT_N(param_count, v));\
return Policy::template FunctionTrait<DynFunction>::MakeReturn();\
}\
};\
};\
\
template <> struct FUN_PROXY_IMPL(param_count) <void >\
{\
template <class DynFunction, DL_REPEAT_N(param_count, typename P), class Policy> struct RetProxy\
{\
static R WINAPI ProxyFun(DL_REPEAT_PARAM_N(param_count, P, v))\
{\
if (DynFunction::InitFunction())\
DynFunction::GetProxy()(DL_REPEAT_N(param_count, v));\
else \
Policy::template FunctionTrait<DynFunction>::MakeReturn();\
}\
};\
};\
\
template <typename R, DL_REPEAT_N(param_count, typename P), class Policy = FunProxyValuePolicy<R> > struct FUN_PROXY(param_count)\
{\
typedef R (WINAPI *fun_type)(DL_REPEAT_N(param_count, P));\
typedef R ret_type;\
template <class DynFunction> struct Proxy:public FUN_PROXY_IMPL(param_count)<R>::template RetProxy<DynFunction, DL_REPEAT_N(param_count, P), Policy>\
{\
};\
};
DECLARE_FUN_PROXY(1)
DECLARE_FUN_PROXY(2)
DECLARE_FUN_PROXY(3)
DECLARE_FUN_PROXY(4)
DECLARE_FUN_PROXY(5)
DECLARE_FUN_PROXY(6)
DECLARE_FUN_PROXY(7)
DECLARE_FUN_PROXY(8)
DECLARE_FUN_PROXY(9)
DECLARE_FUN_PROXY(10)
DECLARE_FUN_PROXY(11)
DECLARE_FUN_PROXY(12)
DECLARE_FUN_PROXY(13)
DECLARE_FUN_PROXY(14)
DECLARE_FUN_PROXY(15)
DECLARE_FUN_PROXY(16)
// usefull macro's
#define USE_MODULE_BEGIN(nmspace, NameId) \
namespace nmspace \
{\
typedef CModule< CNameId<DL_SEQ_ENUM(NameId)> > module_type;
#define USE_MODULE_END \
};
#define DECLARE_FUN_P1(Name, NameId, R, P1) \
static R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId<DL_SEQ_ENUM(NameId)>, FUN_PROXY(1)<R, P1> >::GetProxy();
#define DECLARE_FUN_P1_ERR(Name, NameId, R, P1, E)\
static R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId<DL_SEQ_ENUM(NameId)>, FUN_PROXY(1)<R, P1, FunProxyValuePolicy<R,E> > >::GetProxy();
#define DECLARE_FUN_P1_THROW(Name, NameId, R, P1)\
static R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId<DL_SEQ_ENUM(NameId)>, FUN_PROXY(1)<R, P1, FunProxyThrowPolicy<> > >::GetProxy();
#endif
Здравствуйте, Andrew S, Вы писали:
Как можно заметить код разделяется на два куска — это макросы для повоторения и сам код для загрузки библиотек.
Может стоит выделить для макросов отдельную ветку ?
Все же стоит заменить DWORD, на TCHAR, так нельзя будет ошибиться в написани, вдобавок читать приятней
// DWORD
USE_MODULE_BEGIN(kernel, (kern)(el3)(3.dl)(l)) -> kernel3
// TCHAR
USE_MODULE_BEGIN(kernel, (k)(e)(r)(n)(e)(l)(3)(2)(.)(d)(l)(l) ) -> kernel32.dll
__>Как можно заметить код разделяется на два куска — это макросы для повоторения и сам код для загрузки библиотек.
__>Может стоит выделить для макросов отдельную ветку ?
Может и стоит. У вас есть предложения по макросам? У меня — есть. Например, было бы интересно придумать макрос для разбиения идентификатора на квартеты (или отдельные символы). Тогда можно было бы вообще в нативном синтаксисе писать декларации функций. Конечно, это невозможно скорее всего, но тем не менее. Ну, и конечно, хорошо бы автоматизировать процесс задания макросов декларации функций. Я не смог придумать, как это сделать.
__>Все же стоит заменить DWORD, на TCHAR, так нельзя будет ошибиться в написани, вдобавок читать приятней
Мы уже это обсуждали, мое мнение, что не стоит — слишком длинная запись. Впрочем, это не суть важно.
Меня вот что инетерсует — ваше мнение по поводу деклараций функций в сокращенном виде — делать или нет? Мне думается, что в сокращенном виде особой функциональности не теряется, писать текста меньше почти в 2 раза.
Здравствуйте, Andrew S, Вы писали:
__>>Как можно заметить код разделяется на два куска — это макросы для повоторения и сам код для загрузки библиотек.
__>>Может стоит выделить для макросов отдельную ветку ?
AS>Может и стоит. У вас есть предложения по макросам? У меня — есть. Например, было бы интересно придумать макрос для разбиения идентификатора на квартеты (или отдельные символы). Тогда можно было бы вообще в нативном синтаксисе писать декларации функций. Конечно, это невозможно скорее всего, но тем не менее. Ну, и конечно, хорошо бы автоматизировать процесс задания макросов декларации функций. Я не смог придумать, как это сделать.
Идея :
#define DECLARE_FUN(Name, NameId, R, P1, COMMA1, P2, COMMA2, P3, COMMA3, ...) \
static R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId<DL_SEQ_ENUM(NameId)>, FUN_PROXY(1)<R, P1 COMMA1 P2 COMMA2 ...> >::GetProxy(); // повторение здесь можно через макрос оформить.
использование :
// до
DECLARE_FUN_P1(GetModuleHandle, (GetM)(odul)(eHan)(dleA), HMODULE, LPCTSTR)
// после
DECLARE_FUN(GetModuleHandle, (GetM)(odul)(eHan)(dleA), HMODULE, LPCTSTR, EMPTY, EMPTY ... )
// EMPTY.. можно тоже через макрос оформить - REPEAT_N((сколько надо),EMPTY)
Не очень переносимый вариант :
DECLARE_FUN(GetModuleHandle, (GetM)(odul)(eHan)(dleA), HMODULE, LPCTSTR)
// будет много предупреждений, однако код сработает нормально
__>>Все же стоит заменить DWORD, на TCHAR, так нельзя будет ошибиться в написани, вдобавок читать приятней
AS>Мы уже это обсуждали, мое мнение, что не стоит — слишком длинная запись. Впрочем, это не суть важно.
А что насчет проблемы упомянутой выше ?
AS>Меня вот что инетерсует — ваше мнение по поводу деклараций функций в сокращенном виде — делать или нет? Мне думается, что в сокращенном виде особой функциональности не теряется, писать текста меньше почти в 2 раза.
Не понял про что вы.
А почему бы не сделать так:
#define DECLARE_FUN(name1,name2,name3....) \
CAT(name1,CAT(name2,CAT(name3... ))) // ну или через макрос как-то
DECLARE_FUN(G,e,t,M,o,d,u,l,e,H,a,n,d,l,e, REPEAT_N((сколько надо),EMPTY)
Индефикатор уже разбит, а сложить проще чем разбить
Здравствуйте, Andrew S, Вы писали:
Есть предложение обсудить финальную версию этой вещи по ICQ, а то тема зашла уже довольно далеко.
Мой номер внизу.
__>Идея :
__>__>#define DECLARE_FUN(Name, NameId, R, P1, COMMA1, P2, COMMA2, P3, COMMA3, ...) \
__>static R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId<DL_SEQ_ENUM(NameId)>, FUN_PROXY(1)<R, P1 COMMA1 P2 COMMA2 ...> >::GetProxy(); // повторение здесь можно через макрос оформить.
__>
Я сделал проще (и вероятно, удобнее) — собственно, решение лежало на поверхности:
#define DECLARE_FUN(Name, NameId, R, P) \
static R (WINAPI *&Name)(DL_SEQ_ENUM(P)) = CDynFunction<module_type, CNameId<DL_SEQ_ENUM_CHAR(NameId)>, FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P)> >::GetProxy();
И функции декларируются единообразно для любого числа параметров (до DL_MAX_REPEAT):
USE_MODULE_BEGIN(kernel, (kern)(el32)(.dll))
DECLARE_FUN(GetProcAddress, (GetP)(rocA)(ddre)(ss), FARPROC, (HMODULE)(LPCTSTR))
USE_MODULE_END
А вот слить (GetP)(rocA)(ddre)(ss) в GetProcAddress у меня не получилось. Есть мысли?
__>Есть предложение обсудить финальную версию этой вещи по ICQ, а то тема зашла уже довольно далеко.
__>Мой номер внизу.
__>
Мысль интересная, но если только детали. Обсуждание тут интереснее тем, что другие форумчане могут предложить решения, которых мы просто не видим.
Собственно, версия 1.04
Список изменений :
Изменены порождающие макросы. Теперь для задания функци с любым (DL_MAX_REPEAT) числом параметров используется один тип макросов — DL_DECLARE_FUN_XXX
Изменены названия порождающих макросов
Изменено количество параметров в макросах DL_DECLARE_FUN_XXX — теперь параметр Name убран за ненадобностью
To do
Поддержка MT.
Поддержка соглашений о вызовах кроме __stdcall.
Поддержка функций с переменным числом параметров.
Что то еще?
Как обычно — ждем сообщений о багах, предложений по фичам и прочее-прочее.
// delayimphlp.h: Delay import helper
// Developer: Andrew Solodovnikov
// E-mail: none
// Date: 03.08.2004
#ifndef __DELAYIMPHLP_H__
#define __DELAYIMPHLP_H__
#define DL_CAT_(x,y) x##y
#define DL_CAT(x,y) DL_CAT_(x,y)
#define MAX_DL_REPEAT 16
#define DL_COMMA() ,
#define DL_EMPTY()
// DL_REPEAT_N
#define DL_REPEAT_IMPL_N_0(x, d)
#define DL_REPEAT_IMPL_N_1(x, d) DL_CAT(x,1)
#define DL_REPEAT_IMPL_N_2(x, d) DL_REPEAT_IMPL_N_1(x, d)d() DL_CAT(x,2)
#define DL_REPEAT_IMPL_N_3(x, d) DL_REPEAT_IMPL_N_2(x, d)d() DL_CAT(x,3)
#define DL_REPEAT_IMPL_N_4(x, d) DL_REPEAT_IMPL_N_3(x, d)d() DL_CAT(x,4)
#define DL_REPEAT_IMPL_N_5(x, d) DL_REPEAT_IMPL_N_4(x, d)d() DL_CAT(x,5)
#define DL_REPEAT_IMPL_N_6(x, d) DL_REPEAT_IMPL_N_5(x, d)d() DL_CAT(x,6)
#define DL_REPEAT_IMPL_N_7(x, d) DL_REPEAT_IMPL_N_6(x, d)d() DL_CAT(x,7)
#define DL_REPEAT_IMPL_N_8(x, d) DL_REPEAT_IMPL_N_7(x, d)d() DL_CAT(x,8)
#define DL_REPEAT_IMPL_N_9(x, d) DL_REPEAT_IMPL_N_8(x, d)d() DL_CAT(x,9)
#define DL_REPEAT_IMPL_N_10(x, d) DL_REPEAT_IMPL_N_9(x, d)d() DL_CAT(x,10)
#define DL_REPEAT_IMPL_N_11(x, d) DL_REPEAT_IMPL_N_10(x, d)d() DL_CAT(x,11)
#define DL_REPEAT_IMPL_N_12(x, d) DL_REPEAT_IMPL_N_11(x, d)d() DL_CAT(x,12)
#define DL_REPEAT_IMPL_N_13(x, d) DL_REPEAT_IMPL_N_12(x, d)d() DL_CAT(x,13)
#define DL_REPEAT_IMPL_N_14(x, d) DL_REPEAT_IMPL_N_13(x, d)d() DL_CAT(x,14)
#define DL_REPEAT_IMPL_N_15(x, d) DL_REPEAT_IMPL_N_14(x, d)d() DL_CAT(x,15)
#define DL_REPEAT_IMPL_N_16(x, d) DL_REPEAT_IMPL_N_15(x, d)d() DL_CAT(x,16)
#define DL_REPEAT_IMPL_N(n, x, d) DL_CAT(DL_REPEAT_IMPL_N_,n)(x, d)
#define DL_REPEAT_N(n,x) DL_REPEAT_IMPL_N(n, x, DL_COMMA)
// DL_REPEAT_PARAM_N
#define DL_REPEAT_PARAM_IMPL_N0(n, m, d1, d2)
#define DL_REPEAT_PARAM_IMPL_N1(n, m, d1, d2) DL_CAT(n,1) DL_CAT(m,1)
#define DL_REPEAT_PARAM_IMPL_N2(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N1(n, m, d1, d2)d1() DL_CAT(n,2)d2() DL_CAT(m,2)
#define DL_REPEAT_PARAM_IMPL_N3(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N2(n, m, d1, d2)d1() DL_CAT(n,3)d2() DL_CAT(m,3)
#define DL_REPEAT_PARAM_IMPL_N4(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N3(n, m, d1, d2)d1() DL_CAT(n,4)d2() DL_CAT(m,4)
#define DL_REPEAT_PARAM_IMPL_N5(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N4(n, m, d1, d2)d1() DL_CAT(n,5)d2() DL_CAT(m,5)
#define DL_REPEAT_PARAM_IMPL_N6(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N5(n, m, d1, d2)d1() DL_CAT(n,6)d2() DL_CAT(m,6)
#define DL_REPEAT_PARAM_IMPL_N7(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N6(n, m, d1, d2)d1() DL_CAT(n,7)d2() DL_CAT(m,7)
#define DL_REPEAT_PARAM_IMPL_N8(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N7(n, m, d1, d2)d1() DL_CAT(n,8)d2() DL_CAT(m,8)
#define DL_REPEAT_PARAM_IMPL_N9(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N8(n, m, d1, d2)d1() DL_CAT(n,9)d2() DL_CAT(m,9)
#define DL_REPEAT_PARAM_IMPL_N10(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N9(n, m, d1, d2)d1() DL_CAT(n,10)d2() DL_CAT(m,10)
#define DL_REPEAT_PARAM_IMPL_N11(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N10(n, m, d1, d2)d1() DL_CAT(n,11)d2() DL_CAT(m,11)
#define DL_REPEAT_PARAM_IMPL_N12(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N11(n, m, d1, d2)d1() DL_CAT(n,12)d2() DL_CAT(m,12)
#define DL_REPEAT_PARAM_IMPL_N13(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N12(n, m, d1, d2)d1() DL_CAT(n,13)d2() DL_CAT(m,13)
#define DL_REPEAT_PARAM_IMPL_N14(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N13(n, m, d1, d2)d1() DL_CAT(n,14)d2() DL_CAT(m,14)
#define DL_REPEAT_PARAM_IMPL_N15(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N14(n, m, d1, d2)d1() DL_CAT(n,15)d2() DL_CAT(m,15)
#define DL_REPEAT_PARAM_IMPL_N16(n,m, d1, d2) DL_REPEAT_PARAM_IMPL_N15(n, m, d1, d2)d1() DL_CAT(n,16)d2() DL_CAT(m,16)
#define DL_REPEAT_PARAM_IMPL_N(c, n, m, d1, d2) DL_CAT(DL_REPEAT_PARAM_IMPL_N,c)(n, m, d1, d2)
#define DL_REPEAT_PARAM_N(c, n, m) DL_REPEAT_PARAM_IMPL_N(c, n, m, DL_COMMA, DL_EMPTY)
// DL_REPEAT_DEF_IMPL_N
#define DL_REPEAT_DEF_IMPL_N0(n, def, d)
#define DL_REPEAT_DEF_IMPL_N1(n, def, d) DL_CAT(DL_CAT(n,1), def)
#define DL_REPEAT_DEF_IMPL_N2(n, def, d) DL_REPEAT_DEF_IMPL_N1(n, def, d)d() DL_CAT(DL_CAT(n,2), def)
#define DL_REPEAT_DEF_IMPL_N3(n, def, d) DL_REPEAT_DEF_IMPL_N2(n, def, d)d() DL_CAT(DL_CAT(n,3), def)
#define DL_REPEAT_DEF_IMPL_N4(n, def, d) DL_REPEAT_DEF_IMPL_N3(n, def, d)d() DL_CAT(DL_CAT(n,4), def)
#define DL_REPEAT_DEF_IMPL_N5(n, def, d) DL_REPEAT_DEF_IMPL_N4(n, def, d)d() DL_CAT(DL_CAT(n,5), def)
#define DL_REPEAT_DEF_IMPL_N6(n, def, d) DL_REPEAT_DEF_IMPL_N5(n, def, d)d() DL_CAT(DL_CAT(n,6), def)
#define DL_REPEAT_DEF_IMPL_N7(n, def, d) DL_REPEAT_DEF_IMPL_N6(n, def, d)d() DL_CAT(DL_CAT(n,7), def)
#define DL_REPEAT_DEF_IMPL_N8(n, def, d) DL_REPEAT_DEF_IMPL_N7(n, def, d)d() DL_CAT(DL_CAT(n,8), def)
#define DL_REPEAT_DEF_IMPL_N9(n, def, d) DL_REPEAT_DEF_IMPL_N8(n, def, d)d() DL_CAT(DL_CAT(n,9), def)
#define DL_REPEAT_DEF_IMPL_N10(n, def, d) DL_REPEAT_DEF_IMPL_N9(n, def, d)d() DL_CAT(DL_CAT(n,10), def)
#define DL_REPEAT_DEF_IMPL_N11(n, def, d) DL_REPEAT_DEF_IMPL_N10(n, def, d)d() DL_CAT(DL_CAT(n,11), def)
#define DL_REPEAT_DEF_IMPL_N12(n, def, d) DL_REPEAT_DEF_IMPL_N11(n, def, d)d() DL_CAT(DL_CAT(n,12), def)
#define DL_REPEAT_DEF_IMPL_N13(n, def, d) DL_REPEAT_DEF_IMPL_N12(n, def, d)d() DL_CAT(DL_CAT(n,13), def)
#define DL_REPEAT_DEF_IMPL_N14(n, def, d) DL_REPEAT_DEF_IMPL_N13(n, def, d)d() DL_CAT(DL_CAT(n,14), def)
#define DL_REPEAT_DEF_IMPL_N15(n, def, d) DL_REPEAT_DEF_IMPL_N14(n, def, d)d() DL_CAT(DL_CAT(n,15), def)
#define DL_REPEAT_DEF_IMPL_N16(n, def, d) DL_REPEAT_DEF_IMPL_N15(n, def, d)d() DL_CAT(DL_CAT(n,16), def)
#define DL_REPEAT_DEF_IMPL_N(c, n, def, d) DL_CAT(DL_REPEAT_DEF_IMPL_N,c)(n, def, d)
#define DL_REPEAT_DEF_N(c, n, def) DL_REPEAT_DEF_IMPL_N(c, n, def, DL_COMMA)
// DL_REPEAT_MACRO_N
#define DL_REPEAT_MACRO_IMPL_N0(m, p, d)
#define DL_REPEAT_MACRO_IMPL_N1(m, p, d) m(p,1)
#define DL_REPEAT_MACRO_IMPL_N2(m, p, d) DL_REPEAT_MACRO_IMPL_N1(m, p, d)d() m(p,2)
#define DL_REPEAT_MACRO_IMPL_N3(m, p, d) DL_REPEAT_MACRO_IMPL_N2(m, p, d)d() m(p,3)
#define DL_REPEAT_MACRO_IMPL_N4(m, p, d) DL_REPEAT_MACRO_IMPL_N3(m, p, d)d() m(p,4)
#define DL_REPEAT_MACRO_IMPL_N5(m, p, d) DL_REPEAT_MACRO_IMPL_N4(m, p, d)d() m(p,5)
#define DL_REPEAT_MACRO_IMPL_N6(m, p, d) DL_REPEAT_MACRO_IMPL_N5(m, p, d)d() m(p,6)
#define DL_REPEAT_MACRO_IMPL_N7(m, p, d) DL_REPEAT_MACRO_IMPL_N6(m, p, d)d() m(p,7)
#define DL_REPEAT_MACRO_IMPL_N8(m, p, d) DL_REPEAT_MACRO_IMPL_N7(m, p, d)d() m(p,8)
#define DL_REPEAT_MACRO_IMPL_N9(m, p, d) DL_REPEAT_MACRO_IMPL_N8(m, p, d)d() m(p,9)
#define DL_REPEAT_MACRO_IMPL_N10(m, p, d) DL_REPEAT_MACRO_IMPL_N9(m, p, d)d() m(p,10)
#define DL_REPEAT_MACRO_IMPL_N11(m, p, d) DL_REPEAT_MACRO_IMPL_N10(m, p, d)d() m(p,11)
#define DL_REPEAT_MACRO_IMPL_N12(m, p, d) DL_REPEAT_MACRO_IMPL_N11(m, p, d)d() m(p,12)
#define DL_REPEAT_MACRO_IMPL_N13(m, p, d) DL_REPEAT_MACRO_IMPL_N12(m, p, d)d() m(p,13)
#define DL_REPEAT_MACRO_IMPL_N14(m, p, d) DL_REPEAT_MACRO_IMPL_N13(m, p, d)d() m(p,14)
#define DL_REPEAT_MACRO_IMPL_N15(m, p, d) DL_REPEAT_MACRO_IMPL_N14(m, p, d)d() m(p,15)
#define DL_REPEAT_MACRO_IMPL_N16(m, p, d) DL_REPEAT_MACRO_IMPL_N15(m, p, d)d() m(p,16)
#define DL_REPEAT_MACRO_IMPL_N(c, m, p, d) DL_CAT(DL_REPEAT_MACRO_IMPL_N,c)(m,p, d)
#define DL_REPEAT_MACRO_N(c, m, p) DL_REPEAT_MACRO_IMPL_N(c, m, p, DL_COMMA)
// DL_SEQ_SIZE
#define DL_SEQ_SIZE(seq) DL_SEQ_SIZE_IMPL(seq)
#define DL_SEQ_SIZE_IMPL(seq) DL_CAT(DL_N_, DL_SEQ_SIZE_0 seq)
#define DL_SEQ_SIZE_0(_) DL_SEQ_SIZE_1
#define DL_SEQ_SIZE_1(_) DL_SEQ_SIZE_2
#define DL_SEQ_SIZE_2(_) DL_SEQ_SIZE_3
#define DL_SEQ_SIZE_3(_) DL_SEQ_SIZE_4
#define DL_SEQ_SIZE_4(_) DL_SEQ_SIZE_5
#define DL_SEQ_SIZE_5(_) DL_SEQ_SIZE_6
#define DL_SEQ_SIZE_6(_) DL_SEQ_SIZE_7
#define DL_SEQ_SIZE_7(_) DL_SEQ_SIZE_8
#define DL_SEQ_SIZE_8(_) DL_SEQ_SIZE_9
#define DL_SEQ_SIZE_9(_) DL_SEQ_SIZE_10
#define DL_SEQ_SIZE_10(_) DL_SEQ_SIZE_11
#define DL_SEQ_SIZE_11(_) DL_SEQ_SIZE_12
#define DL_SEQ_SIZE_12(_) DL_SEQ_SIZE_13
#define DL_SEQ_SIZE_13(_) DL_SEQ_SIZE_14
#define DL_SEQ_SIZE_14(_) DL_SEQ_SIZE_15
#define DL_SEQ_SIZE_15(_) DL_SEQ_SIZE_16
#define DL_N_DL_SEQ_SIZE_0 0
#define DL_N_DL_SEQ_SIZE_1 1
#define DL_N_DL_SEQ_SIZE_2 2
#define DL_N_DL_SEQ_SIZE_3 3
#define DL_N_DL_SEQ_SIZE_4 4
#define DL_N_DL_SEQ_SIZE_5 5
#define DL_N_DL_SEQ_SIZE_6 6
#define DL_N_DL_SEQ_SIZE_7 7
#define DL_N_DL_SEQ_SIZE_8 8
#define DL_N_DL_SEQ_SIZE_9 9
#define DL_N_DL_SEQ_SIZE_10 10
#define DL_N_DL_SEQ_SIZE_11 11
#define DL_N_DL_SEQ_SIZE_12 12
#define DL_N_DL_SEQ_SIZE_13 13
#define DL_N_DL_SEQ_SIZE_14 14
#define DL_N_DL_SEQ_SIZE_15 15
#define DL_N_DL_SEQ_SIZE_16 16
// DL_SEQ_ENUM
#define DL_SEQ_ENUM(seq) DL_SEQ_ENUM_IMPL(seq)
#define DL_SEQ_ENUM_IMPL(seq) DL_CAT(DL_SEQ_ENUM_, DL_SEQ_SIZE(seq)) seq
#define DL_SEQ_ENUM_1(x) x
#define DL_SEQ_ENUM_2(x) x, DL_SEQ_ENUM_1
#define DL_SEQ_ENUM_3(x) x, DL_SEQ_ENUM_2
#define DL_SEQ_ENUM_4(x) x, DL_SEQ_ENUM_3
#define DL_SEQ_ENUM_5(x) x, DL_SEQ_ENUM_4
#define DL_SEQ_ENUM_6(x) x, DL_SEQ_ENUM_5
#define DL_SEQ_ENUM_7(x) x, DL_SEQ_ENUM_6
#define DL_SEQ_ENUM_8(x) x, DL_SEQ_ENUM_7
#define DL_SEQ_ENUM_9(x) x, DL_SEQ_ENUM_8
#define DL_SEQ_ENUM_10(x) x, DL_SEQ_ENUM_9
#define DL_SEQ_ENUM_11(x) x, DL_SEQ_ENUM_10
#define DL_SEQ_ENUM_12(x) x, DL_SEQ_ENUM_11
#define DL_SEQ_ENUM_13(x) x, DL_SEQ_ENUM_12
#define DL_SEQ_ENUM_14(x) x, DL_SEQ_ENUM_13
#define DL_SEQ_ENUM_15(x) x, DL_SEQ_ENUM_14
#define DL_SEQ_ENUM_16(x) x, DL_SEQ_ENUM_15
// DL_SEQ_ENUM_CHAR
#define DL_SEQ_ENUM_CHAR(seq) DL_SEQ_ENUM_CHAR_IMPL(seq)
#define DL_SEQ_ENUM_CHAR_IMPL(seq) DL_CAT(DL_SEQ_ENUM_CHAR_, DL_SEQ_SIZE(seq)) seq
#define DL_MAKE_CHAR_(x) #@x
#define DL_MAKE_CHAR(x) DL_MAKE_CHAR_(x)
#define DL_SEQ_ENUM_CHAR_1(x) DL_MAKE_CHAR(x)
#define DL_SEQ_ENUM_CHAR_2(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_1
#define DL_SEQ_ENUM_CHAR_3(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_2
#define DL_SEQ_ENUM_CHAR_4(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_3
#define DL_SEQ_ENUM_CHAR_5(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_4
#define DL_SEQ_ENUM_CHAR_6(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_5
#define DL_SEQ_ENUM_CHAR_7(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_6
#define DL_SEQ_ENUM_CHAR_8(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_7
#define DL_SEQ_ENUM_CHAR_9(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_8
#define DL_SEQ_ENUM_CHAR_10(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_9
#define DL_SEQ_ENUM_CHAR_11(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_10
#define DL_SEQ_ENUM_CHAR_12(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_11
#define DL_SEQ_ENUM_CHAR_13(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_12
#define DL_SEQ_ENUM_CHAR_14(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_13
#define DL_SEQ_ENUM_CHAR_15(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_14
#define DL_SEQ_ENUM_CHAR_16(x) DL_MAKE_CHAR(x), DL_SEQ_ENUM_CHAR_15
// DL_SEQ_ELEM
#define DL_SEQ_ELEM(i, seq) DL_SEQ_ELEM_IMPL(i, seq)
#define DL_SEQ_ELEM_IMPL(i, seq) DL_SEQ_ELEM_IMPL2((DL_CAT(DL_SEQ_ELEM_, i) seq))
#define DL_SEQ_ELEM_IMPL2(par) DL_SEQ_ELEM_IMPL3(DL_SEQ_ELEM_IMPL1 par)
#define DL_SEQ_ELEM_IMPL3(par) par
#define DL_SEQ_ELEM_IMPL1(x, _) x
#define DL_SEQ_ELEM_0(x) x, DL_ELEM_NIL
#define DL_SEQ_ELEM_1(_) DL_SEQ_ELEM_0
#define DL_SEQ_ELEM_2(_) DL_SEQ_ELEM_1
#define DL_SEQ_ELEM_3(_) DL_SEQ_ELEM_2
#define DL_SEQ_ELEM_4(_) DL_SEQ_ELEM_3
#define DL_SEQ_ELEM_5(_) DL_SEQ_ELEM_4
#define DL_SEQ_ELEM_6(_) DL_SEQ_ELEM_5
#define DL_SEQ_ELEM_7(_) DL_SEQ_ELEM_6
#define DL_SEQ_ELEM_8(_) DL_SEQ_ELEM_7
#define DL_SEQ_ELEM_9(_) DL_SEQ_ELEM_8
#define DL_SEQ_ELEM_10(_) DL_SEQ_ELEM_9
#define DL_SEQ_ELEM_11(_) DL_SEQ_ELEM_10
#define DL_SEQ_ELEM_12(_) DL_SEQ_ELEM_11
#define DL_SEQ_ELEM_13(_) DL_SEQ_ELEM_12
#define DL_SEQ_ELEM_14(_) DL_SEQ_ELEM_13
#define DL_SEQ_ELEM_15(_) DL_SEQ_ELEM_14
#define DL_SEQ_ELEM_16(_) DL_SEQ_ELEM_15
#define DL_SEQ_HEAD(seq) DL_SEQ_HEAD_IMPL(seq)
#define DL_SEQ_HEAD_IMPL(seq) DL_SEQ_ELEM(0, seq)
#define DL_SEQ_TAIL(seq) DL_SEQ_TAIL_IMPL(DL_SEQ_TAIL_IMPL1 seq)
#define DL_SEQ_TAIL_IMPL(seq) seq
#define DL_SEQ_TAIL_IMPL1(x)
// DL_SEQ_FOLD_LEFT
#define DL_SEQ_FOLD_LEFT(macro, state, seq) DL_SEQ_FOLD_LEFT_IMPL(macro, state, seq)
#define DL_SEQ_FOLD_LEFT_IMPL(macro, state, seq) DL_CAT(DL_SEQ_FOLD_LEFT_, DL_SEQ_SIZE(seq))(macro, state, seq)
#define DL_SEQ_FOLD_LEFT_0(macro, state, seq) DL_EMPTY()
#define DL_SEQ_FOLD_LEFT_1(macro, state, seq) macro(state, DL_SEQ_ELEM(0, seq))
#define DL_SEQ_FOLD_LEFT_2(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,1)(macro, state, seq), DL_SEQ_ELEM(1, seq))
#define DL_SEQ_FOLD_LEFT_3(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,2)(macro, state, seq), DL_SEQ_ELEM(2, seq))
#define DL_SEQ_FOLD_LEFT_4(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,3)(macro, state, seq), DL_SEQ_ELEM(3, seq))
#define DL_SEQ_FOLD_LEFT_5(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,4)(macro, state, seq), DL_SEQ_ELEM(4, seq))
#define DL_SEQ_FOLD_LEFT_6(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,5)(macro, state, seq), DL_SEQ_ELEM(5, seq))
#define DL_SEQ_FOLD_LEFT_7(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,6)(macro, state, seq), DL_SEQ_ELEM(6, seq))
#define DL_SEQ_FOLD_LEFT_8(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,7)(macro, state, seq), DL_SEQ_ELEM(7, seq))
#define DL_SEQ_FOLD_LEFT_9(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,8)(macro, state, seq), DL_SEQ_ELEM(8, seq))
#define DL_SEQ_FOLD_LEFT_10(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,9)(macro, state, seq), DL_SEQ_ELEM(9, seq))
#define DL_SEQ_FOLD_LEFT_11(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,10)(macro, state, seq), DL_SEQ_ELEM(10, seq))
#define DL_SEQ_FOLD_LEFT_12(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,11)(macro, state, seq), DL_SEQ_ELEM(11, seq))
#define DL_SEQ_FOLD_LEFT_13(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,12)(macro, state, seq), DL_SEQ_ELEM(12, seq))
#define DL_SEQ_FOLD_LEFT_14(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,13)(macro, state, seq), DL_SEQ_ELEM(13, seq))
#define DL_SEQ_FOLD_LEFT_15(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,14)(macro, state, seq), DL_SEQ_ELEM(14, seq))
#define DL_SEQ_FOLD_LEFT_16(macro, state, seq) macro(DL_CAT(DL_SEQ_FOLD_LEFT_,15)(macro, state, seq), DL_SEQ_ELEM(15, seq))
// DL_SEQ_CAT
#define DL_SEQ_CAT(seq) DL_SEQ_CAT_IMPL(seq)
#define DL_SEQ_CAT_IMPL(seq) DL_SEQ_FOLD_LEFT(DL_CAT, DL_SEQ_HEAD(seq), DL_SEQ_TAIL(seq))
// DL_FLATTEN_STR
#define DL_FLATTEN_STR3(val) (((val) > 0xFFFFFF) ? (val) : 0)
#define DL_FLATTEN_STR2(val) (((val) > 0xFFFFFF) ? (val) : DL_FLATTEN_STR3(val << 8))
#define DL_FLATTEN_STR1(val) (((val) > 0xFFFFFF) ? (val) : DL_FLATTEN_STR2(val << 8))
#define DL_FLATTEN_STR0(val) (((val) > 0xFFFFFF) ? (val) : DL_FLATTEN_STR1(val << 8))
#define DL_FLATTEN_STR_(val) \
(TCHAR)HIBYTE(HIWORD(val)), (TCHAR)LOBYTE(HIWORD(val)), (TCHAR)HIBYTE(LOWORD(val)), (TCHAR)LOBYTE(LOWORD(val))
#define DL_FLATTEN_STR(val, num) DL_FLATTEN_STR_(DL_FLATTEN_STR0(DL_CAT(val, num)))
#pragma warning (disable: 4786)
template <int count>
struct CNameIdHolder
{
template <DL_REPEAT_N(MAX_DL_REPEAT, DWORD n)>
struct CNameIdHolderImpl
{
static LPCTSTR GetStr()
{
static const TCHAR szBuffer[] = {
DL_REPEAT_MACRO_N(MAX_DL_REPEAT, DL_FLATTEN_STR, n),
_T('\0' )
};
return szBuffer;
}
};
};
#define NAME_ID_HOLDER_SPEC(num)\
template <>\
struct CNameIdHolder<num>\
{\
template <DL_REPEAT_N(MAX_DL_REPEAT, DWORD n)>\
struct CNameIdHolderImpl\
{\
static LPCTSTR GetStr()\
{\
static const TCHAR szBuffer[] = {\
DL_REPEAT_MACRO_N(num, DL_FLATTEN_STR, n),\
_T('\0' )\
};\
return szBuffer;\
}\
};\
};
NAME_ID_HOLDER_SPEC(15)
NAME_ID_HOLDER_SPEC(14)
NAME_ID_HOLDER_SPEC(13)
NAME_ID_HOLDER_SPEC(12)
NAME_ID_HOLDER_SPEC(11)
NAME_ID_HOLDER_SPEC(10)
NAME_ID_HOLDER_SPEC(9)
NAME_ID_HOLDER_SPEC(8)
NAME_ID_HOLDER_SPEC(7)
NAME_ID_HOLDER_SPEC(6)
NAME_ID_HOLDER_SPEC(5)
NAME_ID_HOLDER_SPEC(4)
NAME_ID_HOLDER_SPEC(3)
NAME_ID_HOLDER_SPEC(2)
NAME_ID_HOLDER_SPEC(1)
template <>
struct CNameIdHolder<0>
{
template <DL_REPEAT_N(MAX_DL_REPEAT, DWORD n)>
struct CNameIdHolderImpl
{
static LPCTSTR GetStr()
{
return NULL;
}
};
};
#define NN_REP_COUNT_M(p, n) (!DL_CAT(p,n)) ? (n-1):
template <DL_REPEAT_DEF_N(MAX_DL_REPEAT, DWORD n, = 0)>
struct CNameId
{
enum
{
DL_REPEAT_PARAM_N(MAX_DL_REPEAT, m_n, =n),
count = DL_REPEAT_MACRO_IMPL_N(MAX_DL_REPEAT, NN_REP_COUNT_M, n, DL_EMPTY) MAX_DL_REPEAT,
length = count * sizeof (DWORD)
};
static LPCTSTR GetStr()
{
return CNameIdHolder<count>::template CNameIdHolderImpl<DL_REPEAT_N(MAX_DL_REPEAT, n)>::GetStr();
}
};
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()
{
m_hModule = LoadLibrary(name_type::GetStr());
}
};
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;
static proxy_type::fun_type &GetProxy()
{
static proxy_type::fun_type proxy = proxy_type::template Proxy<type>::ProxyFun;
return proxy;
}
static BOOL InitFunction()
{
HMODULE hModule = Module::GetModule().m_hModule;
if (hModule)
{
FARPROC pFunction = GetProcAddress(hModule, name_type::GetStr());
if (pFunction)
{
GetProxy() = (proxy_type::fun_type)pFunction;
return TRUE;
}
}
return FALSE;
}
};
struct CDynFunException
{
CDynFunException(): m_sMessage(NULL)
{
};
~CDynFunException()
{
free(m_sMessage);
};
CDynFunException(LPCTSTR sMessage):m_sMessage(NULL)
{
SetMessage(sMessage);
}
CDynFunException(const CDynFunException &other):m_sMessage(NULL)
{
SetMessage(other.m_sMessage);
}
CDynFunException &operator = (const CDynFunException &other)
{
SetMessage(other.m_sMessage);
return *this ;
}
void SetMessage(LPCTSTR sMessage)
{
free(m_sMessage);
m_sMessage = (LPTSTR)malloc((_tcslen(sMessage) + 1) * sizeof (TCHAR));
if (m_sMessage)
_tcscpy(m_sMessage, sMessage);
}
LPCTSTR GetMessage() const
{
return m_sMessage;
}
private :
LPTSTR m_sMessage;
};
template <class R> struct FunProxyThrowRetTypeTrait
{
template <class F>
struct FunctionTraitImpl
{
static R MakeReturn()
{
F::MakeReturnImpl();
return R();
}
};
};
template <> struct FunProxyThrowRetTypeTrait<void >
{
template <class F>
struct FunctionTraitImpl
{
static void MakeReturn()
{
F::MakeReturnImpl();
}
};
};
template <class E = CDynFunException>
struct FunProxyThrowPolicy
{
template <class DynFunction>
struct FunctionTrait:public FunProxyThrowRetTypeTrait<DynFunction::proxy_type::ret_type>::template FunctionTraitImpl<FunctionTrait<DynFunction> >
{
static void MakeReturnImpl()
{
TCHAR szMessage[DynFunction::name_type::length + 64];
_stprintf(szMessage, _T("Can'n resolve procedure <%s>: %d" ), DynFunction::name_type::GetStr(), GetLastError());
throw E(szMessage);
}
};
};
// we need not implement void return type value policy,
// coz void function can only throw on error
template <class R, R value = R()>
struct FunProxyValuePolicy
{
template <class DynFunction>
struct FunctionTrait
{
static DynFunction::proxy_type::ret_type MakeReturn()
{
return value;
}
};
};
#define FUN_PROXY(n) DL_CAT(FunProxy,n)
#define FUN_PROXY_IMPL(n) DL_CAT(FUN_PROXY(n),Impl)
#define DECLARE_FUN_PROXY(param_count) \
template <typename R> struct FUN_PROXY_IMPL(param_count)\
{\
template <class DynFunction, DL_REPEAT_N(param_count, typename P), class Policy> struct RetProxy\
{\
static R WINAPI ProxyFun(DL_REPEAT_PARAM_N(param_count, P, v))\
{\
if (DynFunction::InitFunction())\
return DynFunction::GetProxy()(DL_REPEAT_N(param_count, v));\
return Policy::template FunctionTrait<DynFunction>::MakeReturn();\
}\
};\
};\
\
template <> struct FUN_PROXY_IMPL(param_count) <void >\
{\
template <class DynFunction, DL_REPEAT_N(param_count, typename P), class Policy> struct RetProxy\
{\
static R WINAPI ProxyFun(DL_REPEAT_PARAM_N(param_count, P, v))\
{\
if (DynFunction::InitFunction())\
DynFunction::GetProxy()(DL_REPEAT_N(param_count, v));\
else \
Policy::template FunctionTrait<DynFunction>::MakeReturn();\
}\
};\
};\
\
template <typename R, DL_REPEAT_N(param_count, typename P), class Policy = FunProxyValuePolicy<R> > struct FUN_PROXY(param_count)\
{\
typedef R (WINAPI *fun_type)(DL_REPEAT_N(param_count, P));\
typedef R ret_type;\
template <class DynFunction> struct Proxy:public FUN_PROXY_IMPL(param_count)<R>::template RetProxy<DynFunction, DL_REPEAT_N(param_count, P), Policy>\
{\
};\
};
DECLARE_FUN_PROXY(1)
DECLARE_FUN_PROXY(2)
DECLARE_FUN_PROXY(3)
DECLARE_FUN_PROXY(4)
DECLARE_FUN_PROXY(5)
DECLARE_FUN_PROXY(6)
DECLARE_FUN_PROXY(7)
DECLARE_FUN_PROXY(8)
DECLARE_FUN_PROXY(9)
DECLARE_FUN_PROXY(10)
DECLARE_FUN_PROXY(11)
DECLARE_FUN_PROXY(12)
DECLARE_FUN_PROXY(13)
DECLARE_FUN_PROXY(14)
DECLARE_FUN_PROXY(15)
DECLARE_FUN_PROXY(16)
// usefull macro's
#define DL_USE_MODULE_BEGIN(nmspace, NameId) \
namespace nmspace \
{\
typedef CModule< CNameId<DL_SEQ_ENUM_CHAR(NameId)> > module_type;
#define DL_USE_MODULE_END \
};
#define DL_DECLARE_FUN(NameId, R, P) \
static R (WINAPI *&DL_SEQ_CAT(NameId))(DL_SEQ_ENUM(P)) = CDynFunction<module_type, CNameId<DL_SEQ_ENUM_CHAR(NameId)>, FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P)> >::GetProxy();
#define DL_DECLARE_FUN_ERR(Name, NameId, R, P, E)\
static R (WINAPI *&DL_SEQ_CAT(NameId))(DL_SEQ_ENUM(P)) = CDynFunction<module_type, CNameId<DL_SEQ_ENUM_CHAR(NameId)>, FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P), FunProxyValuePolicy<R,E> > >::GetProxy();
#define DL_DECLARE_FUN_THROW(NameId, R, P)\
static R (WINAPI *&DL_SEQ_CAT(NameId))(DL_SEQ_ENUM(P)) = CDynFunction<module_type, CNameId<DL_SEQ_ENUM_CHAR(NameId)>, FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P), FunProxyThrowPolicy<> > >::GetProxy();
#endif
Re[2]: Код v1.05 - пример использования
Пример использования:
DL_USE_MODULE_BEGIN(kernel, (kern)(el32)(.dll))
DL_DECLARE_FUN((GetP)(rocA)(ddre)(ss), FARPROC, (HMODULE)(LPCTSTR))
DL_DECLARE_FUN((GetM)(odul)(eHan)(dleA), HMODULE, (LPCTSTR))
DL_DECLARE_FUN_THROW((Init)(iali)(zeCr)(itic)(alSe)(ctio)(n), void , (LPCRITICAL_SECTION))
DL_USE_MODULE_END
Re[3]: Код v1.05 - пример использования
Здравствуйте, Andrew S, Вы писали:
AS>Пример использования:
AS>AS>DL_USE_MODULE_BEGIN(kernel, (kern)(el32)(.dll))
AS> DL_DECLARE_FUN((GetP)(rocA)(ddre)(ss), FARPROC, (HMODULE)(LPCTSTR))
AS> DL_DECLARE_FUN((GetM)(odul)(eHan)(dleA), HMODULE, (LPCTSTR))
AS> DL_DECLARE_FUN_THROW((Init)(iali)(zeCr)(itic)(alSe)(ctio)(n), void , (LPCRITICAL_SECTION))
AS>DL_USE_MODULE_END
AS>
(Init)(iali)(zeCr)(itic)(alSe)(ctio)(n)
Ты похоже открыл новое слово в обфускации сорцов:
(HAND)(LE) (file)=(Crea)(teFi)(le)(
(szPa)(th),
(GENE)(RIC_)(WRIT)(E),
(0),(0),
(CREA)(TE_A)(LWAY)(S),
(FILE)(_ATT)(RIBU)(TE_N)(ORMA)(L),
(0));
Зачем, скажи мне, тут вообще потребовались шаблоны для генерации имён ? Ведь макросы сплошные — сделай тогда уж всё на макросах. Я бы генерил макросом функцию, с указаной сигнатурой и именем, а внутри бы имел статический указатель, который бы и заполнял в момент первого вызова. Небольшой оверхед будет, конечно, но зато можно будет писать GetProcAddress вместо (GetP)(rocA)(ddre)(ss).
Здравствуйте, Andrew S, Вы писали:
У меня тут такая мысль возникла а что если в место
template <DL_REPEAT_DEF_N(MAX_DL_REPEAT, DWORD n, = 0)>
struct CNameId
{
enum
{
DL_REPEAT_PARAM_N(MAX_DL_REPEAT, m_n, =n),
count = DL_REPEAT_MACRO_IMPL_N(MAX_DL_REPEAT, NN_REP_COUNT_M, n, DL_EMPTY) MAX_DL_REPEAT,
length = count * sizeof (DWORD)
};
static LPCTSTR GetStr()
{
return CNameIdHolder<count>::template CNameIdHolderImpl<DL_REPEAT_N(MAX_DL_REPEAT, n)>::GetStr();
}
};
#define DL_USE_MODULE_BEGIN(nmspace, NameId) \
namespace nmspace \
{\
typedef CModule< CNameId<DL_SEQ_ENUM_CHAR(NameId)> > module_type;
#define DL_USE_MODULE_END \
};
#define DL_DECLARE_FUN(NameId, R, P) \
static R (WINAPI *&DL_SEQ_CAT(NameId))(DL_SEQ_ENUM(P)) = CDynFunction<module_type, CNameId<DL_SEQ_ENUM_CHAR(NameId)>, FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P)> >::GetProxy();
#define DL_DECLARE_FUN_ERR(Name, NameId, R, P, E)\
static R (WINAPI *&DL_SEQ_CAT(NameId))(DL_SEQ_ENUM(P)) = CDynFunction<module_type, CNameId<DL_SEQ_ENUM_CHAR(NameId)>, FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P), FunProxyValuePolicy<R,E> > >::GetProxy();
#define DL_DECLARE_FUN_THROW(NameId, R, P)\
static R (WINAPI *&DL_SEQ_CAT(NameId))(DL_SEQ_ENUM(P)) = CDynFunction<module_type, CNameId<DL_SEQ_ENUM_CHAR(NameId)>, FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P), FunProxyThrowPolicy<> > >::GetProxy();
DL_USE_MODULE_BEGIN(kernel, (kern)(el32)(.dll))
DL_DECLARE_FUN((GetP)(rocA)(ddre)(ss), FARPROC, (HMODULE)(LPCTSTR))
DL_DECLARE_FUN((GetM)(odul)(eHan)(dleA), HMODULE, (LPCTSTR))
DL_DECLARE_FUN_THROW((Init)(iali)(zeCr)(itic)(alSe)(ctio)(n), void , (LPCRITICAL_SECTION))
DL_USE_MODULE_END
сделать так
#define DL_USE_MODULE_BEGIN(nmspace, Name) \
namespace nmspace \
{\
struct CModuleNameId_##nmspace\
{\
static LPCSTR GetStr(){return Name;}\
};\
typedef CModule< CModuleNameId_##nmspace > module_type;
#define DL_USE_MODULE_END \
};
#define DL_DECLARE_FUN(Name, R, P) \
struct CFunctionNameId_##Name\
{\
static LPCSTR GetStr(){return #Name;}\
};\
static R (WINAPI *&DL_SEQ_CAT(NameId))(DL_SEQ_ENUM(P)) = CDynFunction<module_type, CFunctionNameId_##Name, FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P)> >::GetProxy();
#define DL_DECLARE_FUN_ERR(Name, NameId, R, P, E)\
struct CFunctionNameId_##Name\
{\
static LPCSTR GetStr(){return #Name;}\
};\
static R (WINAPI *&DL_SEQ_CAT(NameId))(DL_SEQ_ENUM(P)) = CDynFunction<module_type, CFunctionNameId_##Name, FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P), FunProxyValuePolicy<R,E> > >::GetProxy();
#define DL_DECLARE_FUN_THROW(NameId, R, P)\
struct CFunctionNameId_##Name\
{\
static LPCSTR GetStr(){return #Name;}\
};\
static R (WINAPI *&DL_SEQ_CAT(NameId))(DL_SEQ_ENUM(P)) = CDynFunction<module_type, CFunctionNameId_##Name, FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P), FunProxyThrowPolicy<> > >::GetProxy();
DL_USE_MODULE_BEGIN(kernel, "kernel32.dll" )
DL_DECLARE_FUN(GetProcAddress, FARPROC, (HMODULE)(LPCTSTR))
DL_DECLARE_FUN(GetModuleHandleA, HMODULE, (LPCTSTR))
DL_DECLARE_FUN_THROW(InitializeCriticalSection, void , (LPCRITICAL_SECTION))
DL_USE_MODULE_END
... << RSDN@Home 1.1.4 rev. 142 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: Код v1.05 - пример использования
CAM>Зачем, скажи мне, тут вообще потребовались шаблоны для генерации имён ? Ведь макросы сплошные — сделай тогда уж всё на макросах. Я бы генерил макросом функцию, с указаной сигнатурой и именем, а внутри бы имел статический указатель, который бы и заполнял в момент первого вызова. Небольшой оверхед будет, конечно, но зато можно будет писать GetProcAddress вместо (GetP)(rocA)(ddre)(ss).
Наверное, вам надо посмотреть хотя бы немного первый вариант кода (который практически без макросов)
. Там ясно видно —
почему и
как . Макросы в дальнейшем появились _только_ для удобства записи.
Re[5]: Код v1.05 - пример использования
CAM>>Зачем, скажи мне, тут вообще потребовались шаблоны для генерации имён ? Ведь макросы сплошные — сделай тогда уж всё на макросах. Я бы генерил макросом функцию, с указаной сигнатурой и именем, а внутри бы имел статический указатель, который бы и заполнял в момент первого вызова. Небольшой оверхед будет, конечно, но зато можно будет писать GetProcAddress вместо (GetP)(rocA)(ddre)(ss).
AS>Наверное, вам надо посмотреть хотя бы немного первый вариант кода (который практически без макросов) . Там ясно видно — почему и как . Макросы в дальнейшем появились _только_ для удобства записи.
А хотя, вкупе с предложение WolfHound можно попробовать и так... и оверхеда не будет. Вот только кросс-модульность. Сейчас попробуем.
WH>У меня тут такая мысль возникла а что если в место
[skipped]
Super! А кросс-модульность будет работать? Т.е. будем ли мы получать один прокси в результате специализаций одинаковыми NameId из разных модулей в этом случае?
(P.S. только что попробовал — все работает, как и следовало ожидать).
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить