Re[4]: Код v1.05
От: WolfHound  
Дата: 23.08.04 15:53
Оценка:
Здравствуйте, Andrew S, Вы писали:

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

1)Что ты понимаешь под модулем?
2)По идеи этот вариант должен работать также как и твой.
... << RSDN@Home 1.1.4 rev. 142 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[5]: Код v1.05
От: Andrew S Россия http://alchemy-lab.com
Дата: 23.08.04 15:56
Оценка:
AS>>Super! А кросс-модульность будет работать? Т.е. будем ли мы получать один прокси в результате специализаций одинаковыми NameId из разных модулей в этом случае?
WH>1)Что ты понимаешь под модулем?
Различные единицы компиляции. Уже проверил — все нормально, одинаковые прокси из разных единиц компиляции находятся после линка по одним адресам.

WH>2)По идеи этот вариант должен работать также как и твой.


Так и работает. Еще раз спасибо — самое очевидно решение я и не заметил. А ведь в первоначальном виде (без темплайтов) у нас идентификатор имени именно так и определялся — при помощит подобных макросов
В общем, похоже мы нашли вариант специализировать шаблоны константной строкой, правда, при маленькой помощи препроцессора
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: код v1.06
От: Andrew S Россия http://alchemy-lab.com
Дата: 23.08.04 16:09
Оценка: 1 (1)
Список изменений:


To do



Да, хорошо бы проверить все это на VC7-7.1... У меня, к сожалению, этих компиляторов нет.
Наверняка, если и не будет компилироваться, можно будет легко устранить причину — ничего особо страшного в коде нет.

//    delayimphlp.h: Delay import helper
//    Developer:    Andrew Solodovnikov
//    E-mail:        none
//    Date:        03.08.2004

#ifndef    __DELAYIMPHLP_H__
#define __DELAYIMPHLP_H__

#pragma warning (disable: 4786)

#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_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


#define NAME_ID(id) DL_CAT(CNameId, id)

#define DECLARE_NAME_ID(id, name)\
struct NAME_ID(id)\
{\
    enum {length = sizeof(name)};\
    static LPCSTR GetStr(){return name;}\
};


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, name) \
namespace nmspace \
{\
    DECLARE_NAME_ID(nmspace, name)\
    typedef CModule<NAME_ID(nmspace)> module_type;

#define DL_USE_MODULE_END \
};

#define DL_DECLARE_FUN(NameId, R, P) \
DECLARE_NAME_ID(NameId, #NameId)\
static R (WINAPI *&NameId)(DL_SEQ_ENUM(P)) = CDynFunction<module_type, NAME_ID(NameId), FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P)> >::GetProxy();

#define DL_DECLARE_FUN_ERR(Name, NameId, R, P, E)\
DECLARE_NAME_ID(NameId, #NameId)\
static R (WINAPI *&NameId)(DL_SEQ_ENUM(P)) = CDynFunction<module_type, NAME_ID(NameId), FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P), FunProxyValuePolicy<R,E> > >::GetProxy();
 
#define DL_DECLARE_FUN_THROW(NameId, R, P)\
DECLARE_NAME_ID(NameId, #NameId)\
static R (WINAPI *&NameId)(DL_SEQ_ENUM(P)) = CDynFunction<module_type, NAME_ID(NameId), FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P), FunProxyThrowPolicy<> > >::GetProxy();
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[6]: Код v1.05
От: WolfHound  
Дата: 23.08.04 16:35
Оценка: +1
Здравствуйте, Andrew S, Вы писали:

AS>Различные единицы компиляции.

Устоявшийся термин "единица трансляции"
... << RSDN@Home 1.1.4 rev. 142 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: код v1.06
От: WolfHound  
Дата: 23.08.04 16:35
Оценка: +1
Здравствуйте, Andrew S, Вы писали:

У меня есть сомнения на счет этой строчки
            _stprintf(szMessage, _T("Can'n resolve procedure <%s>: %d"), DynFunction::name_type::GetStr(), GetLastError());

ИМХО в юникодном проекте сглючит ибо
#define DECLARE_NAME_ID(id, name)\
struct NAME_ID(id)\
{\
    enum {length = sizeof(name)};\
    static LPCSTR GetStr(){return name;}\
};

вот если сделать так
#define DECLARE_NAME_ID(id, name)\
struct NAME_ID(id)\
{\
    enum {length = sizeof(name)};\
    static LPCTSTR GetStr(){return _T(name);}\
};

То должно быть все ОК.

Далие
#define DL_USE_MODULE_BEGIN(nmspace, name) \
namespace nmspace \
{\
    DECLARE_NAME_ID(nmspace, name)\
    typedef CModule<NAME_ID(nmspace)> module_type;

Я бы переделал так
#define DL_USE_MODULE_BEGIN(nmspace, name) \
namespace nmspace \
{\
    DECLARE_NAME_ID(_MODULE_##nmspace, name)\
    typedef CModule<NAME_ID(_MODULE_##nmspace)> module_type;

Так на всякий пожарный
... << RSDN@Home 1.1.4 rev. 142 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: Попытка компиляции в VC7.1
От: adontz Грузия http://adontz.wordpress.com/
Дата: 23.08.04 16:41
Оценка: 14 (1)
Здравствуйте, Andrew S, Вы писали:

строка 171
static proxy_type::fun_type &GetProxy()
заменить на
static typename proxy_type::fun_type &GetProxy()

строка 260
struct FunctionTrait:public FunProxyThrowRetTypeTrait<DynFunction::proxy_type::ret_type>::template FunctionTraitImpl<FunctionTrait<DynFunction> >
заменить на
struct FunctionTrait:public FunProxyThrowRetTypeTrait<typename DynFunction::proxy_type::ret_type>::template FunctionTraitImpl<FunctionTrait<DynFunction> >

строка 281
static DynFunction::proxy_type::ret_type MakeReturn()
заменить на
static typename DynFunction::proxy_type::ret_type MakeReturn()

строка 310
static R WINAPI ProxyFun(DL_REPEAT_PARAM_N(param_count, P, v))\
заменить на
static void WINAPI ProxyFun(DL_REPEAT_PARAM_N(param_count, P, v))\


После чего всё компилируется и даже работает
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[7]: Код v1.05
От: Andrew S Россия http://alchemy-lab.com
Дата: 23.08.04 16:57
Оценка:
AS>>Различные единицы компиляции.
WH>Устоявшийся термин "единица трансляции"

Ок, можно и так. Как барин скажет, так и будем
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[2]: код v1.06
От: adontz Грузия http://adontz.wordpress.com/
Дата: 23.08.04 17:36
Оценка:
Здравствуйте, Andrew S, Вы писали:

  • Поддержка MT.

    В принципе вся "опасная" часть находится внутри InitFunction (я ничего не пропустил?). Самое простое это обернуть её в CriticalSection. Это тормознёт все потоки — что плохо. С другой стороны такой казалось бы легковесный объект как event отожрал у меня около 16 тыс тиков.
    for (int index = 0; index < 100000; index++)
     {
      CloseHandle(CreateEvent(NULL, FALSE, FALSE, _T("EVENT")));
     }

    Mutex отнял приблизительно столько же времени. На этом фоне очень привлекательны критические секции. Они судя по всему раза в 4 быстрее.
    Хотя вобщем-то не известно какие потоки запускает DllMain и как отразиться на программе то, что LoadLibrary вызван из критической секции.

  • Поддержка соглашений о вызовах кроме __stdcall.
  • Поддержка функций с переменным числом параметров.

    ИМХО только с привлечением ассемблера. Надо будет ProxyFun переписать.
    Собственно релиз в VC7.1 как раз и представляет собой то, что надо (параметры шаблонов опущены)
    call        CDynFunction<>::InitFunction (401730h) 
    test        eax,eax 
    je          error: 
    jmp         dword ptr [`CDynFunction<>::GetProxy'::`2'::proxy] 
    error:
    call        FunProxyThrowPolicy<>::MakeReturnImpl

    Как видишь этот код не завязан ни на количество параметров ни на конвенцию вызова.


    P.S. Вызов через такую обёртку даже быстрее вызова через таблицу импорта. Вот я и думаю, а не создать ли продвинутый файл windows (как string.h -> string) в котором все функции будут раскиданы по пространствам имён? Как побочный эффект своего рода антиотладка (передаю привер шароварщикам ) Эдакая МЕГАИДЕЯ
  • A journey of a thousand miles must begin with a single step © Lau Tsu
    Re[3]: код v1.06
    От: WolfHound  
    Дата: 23.08.04 18:19
    Оценка:
    Здравствуйте, WolfHound, Вы писали:

    Придется делать так
    #define DECLARE_NAME_ID(id, name)\
    struct NAME_ID(id)\
    {\
        enum {length = sizeof(name)};\
        static LPCSTR GetStr(){return name;}\
        static LPCTSTR GetTStr(){return _T(name);}\
    };

    Ибо
    FARPROC GetProcAddress(
      HMODULE hModule,    // handle to DLL module
      LPCSTR lpProcName   // function name
    );
    
    HMODULE LoadLibrary(
      LPCTSTR lpFileName   // file name of module
    );

    (C)MSDN
    ... << RSDN@Home 1.1.4 rev. 142 >>
    Пусть это будет просто:
    просто, как только можно,
    но не проще.
    (C) А. Эйнштейн
    Re[3]: код v1.06
    От: Andrew S Россия http://alchemy-lab.com
    Дата: 23.08.04 18:25
    Оценка:
    A>
  • Поддержка MT.

    A>В принципе вся "опасная" часть находится внутри InitFunction (я ничего не пропустил?). Самое простое это обернуть её в CriticalSection. Это тормознёт все потоки — что плохо. С другой стороны такой казалось бы легковесный объект как event отожрал у меня около 16 тыс тиков.


    Верно, но не совсем. На самом деле там 2 места в одной функции — собственно, сама функция и синглтон модуля. Т.е. надо будет по одному объекту синхронизации на модуль + по одному на каждую функцию. На первый взгляд, печально — но на самом деле, все несколько лучше — можно это все обернуть в lightweight mutex'ы — пример приводил WolfHound. Это обеспечит помимо простоты синхронизации еще и всего 4 байта оверхеда на функцию и модуль в MT версии, что имхо немного. Можно вообще LW мутекс привязать только к модулю или же к классу функций (например, сделать его параметр статическим синглтоном без конструктора, как и прокси, по параметру CDynFunction::Name или еще как — надо подумать. В общем, варианты есть, и не такие уж сложные\медленные, тем более, что все это только один раз вызываться будет).
    Вообще, на крайний случай — можно засинхронизировать только синглтон модулей, а сама функция на самом деле вполне реенернабельна.

    A>
  • Поддержка соглашений о вызовах кроме __stdcall.
    A>
  • Поддержка функций с переменным числом параметров.

    Тут придется поправить макросы. Но я подумал — что то расхотелось мне это делать. Не так и много целевых функций имеет отличные от STDCALL конвенции, к тому же в основном это _cdecl с переменным числом параметров, а их все равно легально кроме как через V версии не передать — а они все WINAPI. Т.е. практическая необходимость сомнительна. Поэтому я (пока?) решил на это забить.
  • http://www.rusyaz.ru/pr — стараемся писАть по-русски
    Re[4]: код v1.06
    От: Andrew S Россия http://alchemy-lab.com
    Дата: 23.08.04 18:56
    Оценка:
    WH>Придется делать так
    WH>
    WH>#define DECLARE_NAME_ID(id, name)\
    WH>struct NAME_ID(id)\
    WH>{\
    WH>    enum {length = sizeof(name)};\
    WH>    static LPCSTR GetStr(){return name;}\
    WH>    static LPCTSTR GetTStr(){return _T(name);}\
    WH>};
    WH>


    Ага. Я решил во избежание дублирования анси и не анси строк в юникодной версии (наверное, компиляторы выкинут ненужный код, но лучше не рисковать) сделать так:

    #define DECLARE_NAME_ID_IMPL(id, name, text)\
    struct NAME_ID(id)\
    {\
        enum {length = sizeof(name)};\
        static LPCSTR GetStr(){return text(name);}\
    };
    
    
    #define DECLARE_NAME_ID_A(id, name) DECLARE_NAME_ID_IMPL(id, name, DL_NONE)
    #define DECLARE_NAME_ID(id, name) DECLARE_NAME_ID_IMPL(id, name, _T)
    http://www.rusyaz.ru/pr — стараемся писАть по-русски
    Re[5]: код v1.06б
    От: adontz Грузия http://adontz.wordpress.com/
    Дата: 23.08.04 19:57
    Оценка:
    Здравствуйте, Andrew S, Вы писали:

    Я тут взял на себя наглость прошёлся по коду regex'пами и проч. Изменения под Unicode и под VC7.1 внесены.


    // DelayLoad.h: Delay import helper
    // Developer: Andrew Solodovnikov
    // E-mail: none
    // Date: 23.08.2004
    //
    #pragma once
    //
    #define DL_MERGE_(x,y) x##y
    #define DL_MERGE(x,y) DL_MERGE_(x,y)
    //
    #define DL_COMMA() ,
    #define DL_EMPTY()
    //
    #define DL_REPEAT_IMPL_N_0(x, d)
    #define DL_REPEAT_IMPL_N_1(x, d) DL_MERGE(x,1)
    #define DL_REPEAT_IMPL_N_2(x, d) DL_REPEAT_IMPL_N_1(x, d)d() DL_MERGE(x,2)
    #define DL_REPEAT_IMPL_N_3(x, d) DL_REPEAT_IMPL_N_2(x, d)d() DL_MERGE(x,3)
    #define DL_REPEAT_IMPL_N_4(x, d) DL_REPEAT_IMPL_N_3(x, d)d() DL_MERGE(x,4)
    #define DL_REPEAT_IMPL_N_5(x, d) DL_REPEAT_IMPL_N_4(x, d)d() DL_MERGE(x,5)
    #define DL_REPEAT_IMPL_N_6(x, d) DL_REPEAT_IMPL_N_5(x, d)d() DL_MERGE(x,6)
    #define DL_REPEAT_IMPL_N_7(x, d) DL_REPEAT_IMPL_N_6(x, d)d() DL_MERGE(x,7)
    #define DL_REPEAT_IMPL_N_8(x, d) DL_REPEAT_IMPL_N_7(x, d)d() DL_MERGE(x,8)
    #define DL_REPEAT_IMPL_N_9(x, d) DL_REPEAT_IMPL_N_8(x, d)d() DL_MERGE(x,9)
    #define DL_REPEAT_IMPL_N_10(x, d) DL_REPEAT_IMPL_N_9(x, d)d() DL_MERGE(x,10)
    #define DL_REPEAT_IMPL_N_11(x, d) DL_REPEAT_IMPL_N_10(x, d)d() DL_MERGE(x,11)
    #define DL_REPEAT_IMPL_N_12(x, d) DL_REPEAT_IMPL_N_11(x, d)d() DL_MERGE(x,12)
    #define DL_REPEAT_IMPL_N_13(x, d) DL_REPEAT_IMPL_N_12(x, d)d() DL_MERGE(x,13)
    #define DL_REPEAT_IMPL_N_14(x, d) DL_REPEAT_IMPL_N_13(x, d)d() DL_MERGE(x,14)
    #define DL_REPEAT_IMPL_N_15(x, d) DL_REPEAT_IMPL_N_14(x, d)d() DL_MERGE(x,15)
    #define DL_REPEAT_IMPL_N_16(x, d) DL_REPEAT_IMPL_N_15(x, d)d() DL_MERGE(x,16)
    //
    #define DL_REPEAT_IMPL_N(n, x, d) DL_MERGE(DL_REPEAT_IMPL_N_,n)(x, d)
    //
    #define DL_REPEAT_N(n,x) DL_REPEAT_IMPL_N(n, x, DL_COMMA)
    //
    #define DL_REPEAT_PARAM_IMPL_N0(n, m, d1, d2)
    #define DL_REPEAT_PARAM_IMPL_N1(n, m, d1, d2) DL_MERGE(n,1) DL_MERGE(m,1)
    #define DL_REPEAT_PARAM_IMPL_N2(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N1(n, m, d1, d2)d1() DL_MERGE(n,2)d2() DL_MERGE(m,2)
    #define DL_REPEAT_PARAM_IMPL_N3(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N2(n, m, d1, d2)d1() DL_MERGE(n,3)d2() DL_MERGE(m,3)
    #define DL_REPEAT_PARAM_IMPL_N4(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N3(n, m, d1, d2)d1() DL_MERGE(n,4)d2() DL_MERGE(m,4)
    #define DL_REPEAT_PARAM_IMPL_N5(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N4(n, m, d1, d2)d1() DL_MERGE(n,5)d2() DL_MERGE(m,5)
    #define DL_REPEAT_PARAM_IMPL_N6(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N5(n, m, d1, d2)d1() DL_MERGE(n,6)d2() DL_MERGE(m,6)
    #define DL_REPEAT_PARAM_IMPL_N7(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N6(n, m, d1, d2)d1() DL_MERGE(n,7)d2() DL_MERGE(m,7)
    #define DL_REPEAT_PARAM_IMPL_N8(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N7(n, m, d1, d2)d1() DL_MERGE(n,8)d2() DL_MERGE(m,8)
    #define DL_REPEAT_PARAM_IMPL_N9(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N8(n, m, d1, d2)d1() DL_MERGE(n,9)d2() DL_MERGE(m,9)
    #define DL_REPEAT_PARAM_IMPL_N10(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N9(n, m, d1, d2)d1() DL_MERGE(n,10)d2() DL_MERGE(m,10)
    #define DL_REPEAT_PARAM_IMPL_N11(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N10(n, m, d1, d2)d1() DL_MERGE(n,11)d2() DL_MERGE(m,11)
    #define DL_REPEAT_PARAM_IMPL_N12(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N11(n, m, d1, d2)d1() DL_MERGE(n,12)d2() DL_MERGE(m,12)
    #define DL_REPEAT_PARAM_IMPL_N13(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N12(n, m, d1, d2)d1() DL_MERGE(n,13)d2() DL_MERGE(m,13)
    #define DL_REPEAT_PARAM_IMPL_N14(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N13(n, m, d1, d2)d1() DL_MERGE(n,14)d2() DL_MERGE(m,14)
    #define DL_REPEAT_PARAM_IMPL_N15(n, m, d1, d2) DL_REPEAT_PARAM_IMPL_N14(n, m, d1, d2)d1() DL_MERGE(n,15)d2() DL_MERGE(m,15)
    #define DL_REPEAT_PARAM_IMPL_N16(n,m, d1, d2) DL_REPEAT_PARAM_IMPL_N15(n, m, d1, d2)d1() DL_MERGE(n,16)d2() DL_MERGE(m,16)
    //
    #define DL_REPEAT_PARAM_IMPL_N(c, n, m, d1, d2) DL_MERGE(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)
    //
    #define DL_SEQ_SIZE(seq) DL_SEQ_SIZE_IMPL(seq)
    #define DL_SEQ_SIZE_IMPL(seq) DL_MERGE(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_MERGE(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
    //
    #define NAME_ID(id) DL_MERGE(CNameId, id)
    //
    #define DECLARE_NAME_ID(id, name, TYPE, modifier)\
    struct NAME_ID(id)\
        {\
            enum {length = sizeof(name)};\
            static TYPE GetStr() { return modifier(name); }\
        };
    //
    #define DECLARE_NAME_ID_A(id, name) DECLARE_NAME_ID(id, name, LPCSTR, DL_EMPTY() )
    #define DECLARE_NAME_ID_T(id, name) DECLARE_NAME_ID(id, name, LPCTSTR, TEXT)
    //
    template <class Name>
    class CModule
        {
            public:
                HMODULE m_hModule;
            public:
                typedef CModule<Name> type;
                typedef Name name_type;
            public:
                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;
            public:
                static typename proxy_type::fun_type &GetProxy()
                    {
                        static proxy_type::fun_type proxy = proxy_type::template Proxy<type>::ProxyFun;
                        return proxy;
                    }
                static BOOL InitFunction()
                    {
                        if (Module::GetModule().m_hModule)
                            {
                                FARPROC lpFunction = GetProcAddress(Module::GetModule().m_hModule, name_type::GetStr());
                                if (lpFunction)
                                    {
                                        GetProxy() = (proxy_type::fun_type)lpFunction;
                                        return TRUE;
                                    }
                            }
                        return FALSE;
                    }
        };
    //
    class CDynFunException
        {
            public:
                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<typename 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);
                            }
                };
        };
    //
    template<class R, R value = R()>
    struct FunProxyValuePolicy
        {
            template <class DynFunction>
            struct FunctionTrait
                {
                    static typename DynFunction::proxy_type::ret_type MakeReturn()
                        {
                            return value;
                        }
                };
        };
    //
    #define DL_FUN_PROXY(n) DL_MERGE(FunProxy,n)
    #define DL_FUN_PROXY_IMPL(n) DL_MERGE(DL_FUN_PROXY(n),Impl)
    //
    #define DECLARE_FUN_PROXY(param_count) \
    template <typename R> \
    struct DL_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)); \
                                } \
                            else \
                                { \
                                    return Policy::template FunctionTrait<DynFunction>::MakeReturn(); \
                                } \
                        }\
                };\
        };\
    \
    template <> \
    struct DL_FUN_PROXY_IMPL(param_count) <void> \
        { \
            template <class DynFunction, DL_REPEAT_N(param_count, typename P), class Policy> \
            struct RetProxy \
                { \
                    static void 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 DL_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 DL_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)
    //
    #define DL_USE_MODULE_BEGIN(nmspace, name) \
    namespace nmspace \
        { \
            DECLARE_NAME_ID_T(_MODULE_##nmspace, name) \
            typedef CModule<NAME_ID(_MODULE_##nmspace)> module_type;
    //
    #define DL_USE_MODULE_END \
        };
    //
    #define DL_DECLARE_FUN(NameId, R, P) \
    DECLARE_NAME_ID_A(NameId, #NameId) \
    static R (WINAPI *&NameId)(DL_SEQ_ENUM(P)) = CDynFunction<module_type, NAME_ID(NameId), DL_FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P)> >::GetProxy();
    //
    #define DL_DECLARE_FUN_ERR(Name, NameId, R, P, E) \
    DECLARE_NAME_ID_A(NameId, #NameId) \
    static R (WINAPI *&NameId)(DL_SEQ_ENUM(P)) = CDynFunction<module_type, NAME_ID(NameId), DL_FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P), FunProxyValuePolicy<R,E> > >::GetProxy();
    //
    #define DL_DECLARE_FUN_THROW(NameId, R, P) \
    DECLARE_NAME_ID_A(NameId, #NameId) \
    static R (WINAPI *&NameId)(DL_SEQ_ENUM(P)) = CDynFunction<module_type, NAME_ID(NameId), DL_FUN_PROXY(DL_SEQ_SIZE(P))<R, DL_SEQ_ENUM(P), FunProxyThrowPolicy<> > >::GetProxy();
    //
    // End of file
    //
    A journey of a thousand miles must begin with a single step © Lau Tsu
    Re[6]: код v1.06б
    От: Andrew S Россия http://alchemy-lab.com
    Дата: 23.08.04 20:31
    Оценка:
    A>Я тут взял на себя наглость прошёлся по коду regex'пами и проч. Изменения под Unicode и под VC7.1 внесены.

    Не, мне такое форматирование не нравится Не по стандарту (нашему, по крайней мере). Одни отсупы {} чего стоят. Да и переименование макроса CAT в MERGE тоже не по стандарту — в бусте именно CAT и хочется этому хоть как то соответствовать. Опять же, у меня еще несколько изменений касательно авто-поддержки юникода (да, да, именно авто поддержки, на основе заголовков от обычных, статически линкуемых бибилотек), которые я тут еще не отражал. В общем, думаю, пока что не стоит форматировать сурсы (по крайней мере публично — локально можно конечно делать что угодно ) — бесполезный труд, у меня еще слишком много чего есть, и конкатенировать после таких изменений сложно Но в любом случае — спасибо за попытку!
    http://www.rusyaz.ru/pr — стараемся писАть по-русски
    Re[7]: код v1.06б
    От: adontz Грузия http://adontz.wordpress.com/
    Дата: 23.08.04 21:55
    Оценка:
    Здравствуйте, Andrew S, Вы писали:

    AS>Да и переименование макроса CAT в MERGE тоже не по стандарту — в бусте именно CAT и хочется этому хоть как-то соответствовать.


    Это совершенно не соответствует англо-русскому словарю В доке к ## preprocessor operator так и написано

    The double-number-sign or "token-pasting" operator (##), which is sometimes called the "merging" operator, is used in both object-like and function-like macros.

    А о чём думали в бусте я не знаю Cat это кошка Я кошек люблю, но здесь они не к месту.

    AS>Опять же, у меня еще несколько изменений касательно авто-поддержки юникода (да, да, именно авто поддержки, на основе заголовков от обычных, статически линкуемых бибилотек), которые я тут еще не отражал.


    А что ещё? Там же макросы типа
    #ifdef _UNICODE
    #define Func FuncW
    #else
    #define Func FuncA
    #endif

    Что ещё туда добавлять? Func на FuncA или FuncW будет заменятся вне зависимости он нашего желания. Со структурами тоже самое. В unicode я это дело уже компилировал (1.06б) всё ОК.
    Я что-то упустил?

    AS>В общем, думаю, пока что не стоит форматировать сурсы (по крайней мере публично — локально можно конечно делать что угодно ) — бесполезный труд, у меня еще слишком много чего есть, и конкатенировать после таких изменений сложно Но в любом случае — спасибо за попытку!


    Отступы только делай табуляцией.
    A journey of a thousand miles must begin with a single step © Lau Tsu
    Re[8]: код v1.06б
    От: Andrew S Россия http://alchemy-lab.com
    Дата: 23.08.04 22:03
    Оценка:
    AS>>Да и переименование макроса CAT в MERGE тоже не по стандарту — в бусте именно CAT и хочется этому хоть как-то соответствовать.

    A>Это совершенно не соответствует англо-русскому словарю В доке к ## preprocessor operator так и написано


    Соответствует.
    A>А о чём думали в бусте я не знаю Cat это кошка Я кошек люблю, но здесь они не к месту.

    Это сокращение от concatenate и достаточно точно отражает смысл, как мне кажется В отличие от MERGE — которое значит совмещать, но не соединять. Вообше, merge на мой взгляд больше применим к множествам, а конкатинация — к последовательностям.

    AS>>Опять же, у меня еще несколько изменений касательно авто-поддержки юникода (да, да, именно авто поддержки, на основе заголовков от обычных, статически линкуемых бибилотек), которые я тут еще не отражал.


    A>А что ещё? Там же макросы типа

    A>
    A>#ifdef _UNICODE
    A>#define Func FuncW
    A>#else
    A>#define Func FuncA
    A>#endif
    A>

    A>Что ещё туда добавлять? Func на FuncA или FuncW будет заменятся вне зависимости он нашего желания. Со структурами тоже самое. В unicode я это дело уже компилировал (1.06б) всё ОК.
    A>Я что-то упустил?

    Конечно. В текущей версии DECLARE_NAME_ID(NameId, #NameId) раскроет LoadLibrary именно в "LoadLibrary" вне зависимости от нашего (не)желания.
    AS>>В общем, думаю, пока что не стоит форматировать сурсы (по крайней мере публично — локально можно конечно делать что угодно ) — бесполезный труд, у меня еще слишком много чего есть, и конкатенировать после таких изменений сложно Но в любом случае — спасибо за попытку!

    A>Отступы только делай табуляцией.


    Дык я вроде ей и делаю (точнее, VAssist делает). Если где что и упустил — или по своему недосмотру, или спостил изменения с форума. Или ты имеешь ввиду отсуп между типом и именем определения (ну или директивой\именем)? Там да, я по-привычке ставлю пробелы. Попробую поправить.
    http://www.rusyaz.ru/pr — стараемся писАть по-русски
    Re[9]: код v1.06б
    От: adontz Грузия http://adontz.wordpress.com/
    Дата: 23.08.04 22:25
    Оценка:
    Здравствуйте, Andrew S, Вы писали:

    AS>Это сокращение от concatenate и достаточно точно отражает смысл, как мне кажется В отличие от MERGE — которое значит совмещать, но не соединять.

    Скорее объединять.

    AS>Вообше, merge на мой взгляд больше применим к множествам, а конкатинация — к последовательностям.

    Ну я за имя не дерусь, используется этот макрос всё равно только в служебных целях. Просто для меня оно показалось непонятным.

    AS>Конечно. В текущей версии DECLARE_NAME_ID(NameId, #NameId) раскроет LoadLibrary именно в "LoadLibrary" вне зависимости от нашего (не)желания.


    Ну и? У одних функций есть A/W версии у других нету. ИМХО лучше сделать
    DL_USE_MODULE_BEGIN(kernel, "kernel32.dll")
        DL_DECLARE_FUN(GetModuleHandleA, HMODULE, (LPCSTR))
        DL_DECLARE_FUN(GetModuleHandleW, HMODULE, (LPCWSTR))
    DL_USE_MODULE_END
    чем
    DL_USE_MODULE_BEGIN(kernel, "kernel32.dll")
        DL_DECLARE_FUN_DUAL(GetModuleHandle, HMODULE, (LPC??что здесь писать??STR))
    DL_USE_MODULE_END

    A>>Отступы только делай табуляцией.
    AS>Дык я вроде ей и делаю (точнее, VAssist делает).

    Нет, это я зря ругаюсь. Если копировать с сайта, то по любому пробелы, даже если в исходном сообщении табуляция.
    Единственный шанс получить текст с табуляцией это копировать из цитирования в форме ответа
    Зато если в студии выделить всё и нажать Tab, Shift+Tab то всё будет как надо но это в 7.1, а в 6ке не знаю как.
    A journey of a thousand miles must begin with a single step © Lau Tsu
    Re[10]: код v1.06б
    От: Andrew S Россия http://alchemy-lab.com
    Дата: 24.08.04 07:39
    Оценка:
    A>Ну и? У одних функций есть A/W версии у других нету. ИМХО лучше сделать
    A>
    A>DL_USE_MODULE_BEGIN(kernel, "kernel32.dll")
    A>    DL_DECLARE_FUN(GetModuleHandleA, HMODULE, (LPCSTR))
    A>    DL_DECLARE_FUN(GetModuleHandleW, HMODULE, (LPCWSTR))
    A>DL_USE_MODULE_END
    A>
    чем

    A>
    A>DL_USE_MODULE_BEGIN(kernel, "kernel32.dll")
    A>    DL_DECLARE_FUN_DUAL(GetModuleHandle, HMODULE, (LPC??что здесь писать??STR))
    A>DL_USE_MODULE_END
    A>


    А здесь писать
    DL_USE_MODULE_BEGIN(kernel, "kernel32.dll")
    DL_DECLARE_FUN_DUAL(GetModuleHandle, HMODULE, (LPCTSTR))
    DL_USE_MODULE_END

    В этом то и фишка. На самом деле, за нас все сделает препроцессор, маленький трюк, как и с CAT, на самом деле — заставить его вывести макрос до дальнейшего препроцессирования.

    A>>>Отступы только делай табуляцией.

    AS>>Дык я вроде ей и делаю (точнее, VAssist делает).

    A>Нет, это я зря ругаюсь. Если копировать с сайта, то по любому пробелы, даже если в исходном сообщении табуляция.

    A>Единственный шанс получить текст с табуляцией это копировать из цитирования в форме ответа
    A>Зато если в студии выделить всё и нажать Tab, Shift+Tab то всё будет как надо но это в 7.1, а в 6ке не знаю как.

    У меня вроде как с табами копируется, а если целевой редактор понимает — то даже и RTF. VAssist — великая штука.
    http://www.rusyaz.ru/pr — стараемся писАть по-русски
    Re[2]: код v1.06
    От: _nn_ www.nemerleweb.com
    Дата: 24.08.04 08:07
    Оценка:
    Здравствуйте, Andrew S, Вы писали:

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


    AS>[list]

    AS>Изменены порождающие макросы (спасибо WolfHound). Теперь синтаксис стал гораздо более очевидным и нативным:
    AS>
    AS>DL_USE_MODULE_BEGIN(kernel, "kernel32.dll")
    AS>    DL_DECLARE_FUN(GetProcAddress, FARPROC, (HMODULE)(LPCTSTR))
    AS>    DL_DECLARE_FUN(GetModuleHandleA, HMODULE, (LPCTSTR))
    AS>    DL_DECLARE_FUN_THROW(InitializeCriticalSection, void, (LPCRITICAL_SECTION))
    AS>DL_USE_MODULE_END
    AS>


    Маленкое замечание :

    Что будет если написать так :
    DL_USE_MODULE_BEGIN(kernel, L"kernel32.dll")


    Мне кажется в CNameId будет немного неправильные значения.

    Решение 1 :
    передавать тип в макрос :
    DL_USE_MODULE_BEGIN(kernel, WCHAR, L"kernel32.dll")


    Решение 2 :
    Сделать два набора классов :
    template<typename T>
    CNameIdT {...}
    
    typedef CNameIdT<CHAR> CNameIdA;
    typedef CNameIdT<WCHAR> CNameIdW;
    
    #ifdef UNICODE
    typedef CNameIdW CNameId;
    #define DL_USE_MODULE_BEGIN DL_USE_MODULE_BEGIN_W
    #else
    typedef CNameIdA CNameId;
    #define DL_USE_MODULE_BEGIN DL_USE_MODULE_BEGIN_A
    #endif
    
    // явно
    DL_USE_MODULE_BEGIN_A(kernel, "kernel32.dll")
    DL_USE_MODULE_BEGIN_W(kernel, L"kernel32.dll")
    
    // неявно
    DL_USE_MODULE_BEGIN(kernel, "kernel32.dll")
    http://rsdn.nemerleweb.com
    http://nemerleweb.com
    Re[2]: код v1.06
    От: CAMAD Россия  
    Дата: 24.08.04 10:59
    Оценка:
    Здравствуйте, Andrew S, Вы писали:

    ...

    AS>To do


    AS>Поддержка MT.


    Я не вижу проблемы с MT. Запись/чтение выравненного двойного слова атомарна, поэтому худшее, что может быть — лишний вызов GetProcAddress.

    Ещё у меня предложение — вместо разных макросов, для разных способов обработки ошибок позволить в макросе указывать функцию-обработчик, с таким же возвращаемым значенем, как и генерируемая функция. Таким образом будет выбор, или возвратить что-то инвалидное, или сделать throw / RaiseException. Кроме того, исчезнет зависимость от sprintf'а. Конечно, указывать в каждой функции обработчик ошибок — накладно, пока могу предложить только "глобальный" обработчик, который будет указываться в DL_USE_MODULE_BEGIN.

    Кстати, я вижу, что ошибки с LoadModule никак не обрабатываются, и единственный способ узнать, что dll'ки нет — это самостоятельно проверить CModule::GetModule на 0.
    Re[3]: код v1.06
    От: CAMAD Россия  
    Дата: 24.08.04 11:02
    Оценка:
    Здравствуйте, CAMAD, Вы писали:

    ...

    CAM>Кстати, я вижу, что ошибки с LoadModule никак не обрабатываются, и единственный способ узнать, что dll'ки нет — это самостоятельно проверить CModule::GetModule на 0.


    Имелось в виду LoadLibrary.
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.