Re[3]: Pure C++ delay load
От: Andrew S Россия http://alchemy-lab.com
Дата: 18.08.04 13:22
Оценка:
__>Есть идея, но она мне кажется неосуществима.
__>Что-то такое :
__>
__>#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 во время компиляции, размер буфера под целое тоже. Просто лень было (да и важнее проблемы были и есть) — я политики для исключений сделал больше просто для того, дабы показать, что очень просто расширить предлагаемый функционал.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[4]: Pure C++ delay load
От: _nn_ www.nemerleweb.com
Дата: 18.08.04 15:41
Оценка:
Здравствуйте, 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 во время компиляции, размер буфера под целое тоже. Просто лень было (да и важнее проблемы были и есть) — я политики для исключений сделал больше просто для того, дабы показать, что очень просто расширить предлагаемый функционал.

Ясно.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Код v1.04
От: Andrew S Россия http://alchemy-lab.com
Дата: 20.08.04 11:00
Оценка:
Собственно, версия 1.04

Список изменений:


To do


Как обычно — ждем сообщений о багах, предложений по фичам и прочее-прочее.


//    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
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[2]: Код v1.04
От: _nn_ www.nemerleweb.com
Дата: 20.08.04 13:20
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Собственно, версия 1.04


AS>Список изменений:


AS>

Наверное все же стоит в структуре CDynFunException член m_sMessage сделать приватным, мало ли что будет
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Код v1.04
От: Andrew S Россия http://alchemy-lab.com
Дата: 20.08.04 13:31
Оценка:
__>Наверное все же стоит в структуре CDynFunException член m_sMessage сделать приватным, мало ли что будет

Done. Впрочем, когда выбрасывается исключение, то мало уже не будет
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[2]: Код v1.04
От: _nn_ www.nemerleweb.com
Дата: 20.08.04 18:40
Оценка:
Здравствуйте, Andrew S, Вы писали:

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++, если на других компиляторах также то проблем нет.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Код v1.05a
От: Andrew S Россия http://alchemy-lab.com
Дата: 21.08.04 18:34
Оценка:
>>Компилеро-независимый способ задания строк, сейчас работает только на линейке 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
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[2]: Код v1.05a
От: _nn_ www.nemerleweb.com
Дата: 22.08.04 05:53
Оценка:
Здравствуйте, 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
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Код v1.05a
От: Andrew S Россия http://alchemy-lab.com
Дата: 22.08.04 10:26
Оценка:
__>Как можно заметить код разделяется на два куска — это макросы для повоторения и сам код для загрузки библиотек.
__>Может стоит выделить для макросов отдельную ветку ?

Может и стоит. У вас есть предложения по макросам? У меня — есть. Например, было бы интересно придумать макрос для разбиения идентификатора на квартеты (или отдельные символы). Тогда можно было бы вообще в нативном синтаксисе писать декларации функций. Конечно, это невозможно скорее всего, но тем не менее. Ну, и конечно, хорошо бы автоматизировать процесс задания макросов декларации функций. Я не смог придумать, как это сделать.

__>Все же стоит заменить DWORD, на TCHAR, так нельзя будет ошибиться в написани, вдобавок читать приятней


Мы уже это обсуждали, мое мнение, что не стоит — слишком длинная запись. Впрочем, это не суть важно.
Меня вот что инетерсует — ваше мнение по поводу деклараций функций в сокращенном виде — делать или нет? Мне думается, что в сокращенном виде особой функциональности не теряется, писать текста меньше почти в 2 раза.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[4]: Код v1.05a
От: _nn_ www.nemerleweb.com
Дата: 22.08.04 10:49
Оценка:
Здравствуйте, 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)

Индефикатор уже разбит, а сложить проще чем разбить
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: Код v1.05a
От: _nn_ www.nemerleweb.com
Дата: 22.08.04 10:56
Оценка:
Здравствуйте, Andrew S, Вы писали:

Есть предложение обсудить финальную версию этой вещи по ICQ, а то тема зашла уже довольно далеко.
Мой номер внизу.

http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Код v1.05a
От: Andrew S Россия http://alchemy-lab.com
Дата: 22.08.04 11:50
Оценка:
__>Идея :
__>
__>#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 у меня не получилось. Есть мысли?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[5]: Код v1.05a
От: Andrew S Россия http://alchemy-lab.com
Дата: 22.08.04 11:51
Оценка:
__>Есть предложение обсудить финальную версию этой вещи по ICQ, а то тема зашла уже довольно далеко.
__>Мой номер внизу.

__>


Мысль интересная, но если только детали. Обсуждание тут интереснее тем, что другие форумчане могут предложить решения, которых мы просто не видим.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: Код v1.05
От: Andrew S Россия http://alchemy-lab.com
Дата: 23.08.04 12:40
Оценка:
Собственно, версия 1.04

Список изменений:


To do


Как обычно — ждем сообщений о багах, предложений по фичам и прочее-прочее.



//    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
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[2]: Код v1.05 - пример использования
От: Andrew S Россия http://alchemy-lab.com
Дата: 23.08.04 12:45
Оценка:
Пример использования:

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
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: Код v1.05 - пример использования
От: CAMAD Россия  
Дата: 23.08.04 13:57
Оценка: 1 (1)
Здравствуйте, 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).
Re[2]: Код v1.05
От: WolfHound  
Дата: 23.08.04 15:00
Оценка: 21 (1)
Здравствуйте, 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 - пример использования
От: Andrew S Россия http://alchemy-lab.com
Дата: 23.08.04 15:05
Оценка:
CAM>Зачем, скажи мне, тут вообще потребовались шаблоны для генерации имён ? Ведь макросы сплошные — сделай тогда уж всё на макросах. Я бы генерил макросом функцию, с указаной сигнатурой и именем, а внутри бы имел статический указатель, который бы и заполнял в момент первого вызова. Небольшой оверхед будет, конечно, но зато можно будет писать GetProcAddress вместо (GetP)(rocA)(ddre)(ss).

Наверное, вам надо посмотреть хотя бы немного первый вариант кода (который практически без макросов) . Там ясно видно — почему и как. Макросы в дальнейшем появились _только_ для удобства записи.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[5]: Код v1.05 - пример использования
От: Andrew S Россия http://alchemy-lab.com
Дата: 23.08.04 15:18
Оценка:
CAM>>Зачем, скажи мне, тут вообще потребовались шаблоны для генерации имён ? Ведь макросы сплошные — сделай тогда уж всё на макросах. Я бы генерил макросом функцию, с указаной сигнатурой и именем, а внутри бы имел статический указатель, который бы и заполнял в момент первого вызова. Небольшой оверхед будет, конечно, но зато можно будет писать GetProcAddress вместо (GetP)(rocA)(ddre)(ss).

AS>Наверное, вам надо посмотреть хотя бы немного первый вариант кода (который практически без макросов) . Там ясно видно — почему и как. Макросы в дальнейшем появились _только_ для удобства записи.


А хотя, вкупе с предложение WolfHound можно попробовать и так... и оверхеда не будет. Вот только кросс-модульность. Сейчас попробуем.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: Код v1.05
От: Andrew S Россия http://alchemy-lab.com
Дата: 23.08.04 15:25
Оценка:
WH>У меня тут такая мысль возникла а что если в место
[skipped]

Super! А кросс-модульность будет работать? Т.е. будем ли мы получать один прокси в результате специализаций одинаковыми NameId из разных модулей в этом случае?

(P.S. только что попробовал — все работает, как и следовало ожидать).
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.