Re: Сам код
От: Andrew S Россия http://alchemy-lab.com
Дата: 05.08.04 13:20
Оценка:
Все в куче, уж не обессудьте.
#define FLATTEN_STR(buff, name, idx) \
        (buff)[4*(idx)] = (TCHAR)((name##idx & 0xFF000000) >> 24);\
        (buff)[4*(idx) + 1] = (TCHAR)((name##idx & 0xFF0000) >> 16);\
        (buff)[4*(idx) + 2] = (TCHAR)((name##idx & 0xFF00) >> 8);\
        (buff)[4*(idx) + 3] = (TCHAR)(name##idx & 0xFF);

void FlattenStr(LPSTR szBuffer, DWORD n0, DWORD n1, DWORD n2, DWORD n3, DWORD n4, DWORD n5, DWORD n6, DWORD n7)
{
        FLATTEN_STR(szBuffer, n, 0);
        FLATTEN_STR(szBuffer, n, 1);
        FLATTEN_STR(szBuffer, n, 2);
        FLATTEN_STR(szBuffer, n, 3);
        FLATTEN_STR(szBuffer, n, 4);
        FLATTEN_STR(szBuffer, n, 5);
        FLATTEN_STR(szBuffer, n, 6);
        FLATTEN_STR(szBuffer, n, 7);
        szBuffer[64] = _T('\0');
}


template <DWORD n0 = 0, DWORD n1 = 0, DWORD n2 = 0, DWORD n3 = 0, DWORD n4 = 0, DWORD n5 = 0, DWORD n6 = 0, DWORD n7 = 0>
struct CNameId
{
    enum {name_size = 65, m_n0 = n0, m_n1 = n1, m_n2 = n2, m_n3 = n3, m_n4 = n4, m_n5 = n5, m_n6 = n6, m_n7 = n7};
    static void MakeStr(LPTSTR szBuffer)
    {
        FlattenStr(szBuffer, n0,n1,n2,n3,n4,n5,n6,n7);
    }
};

template <class Name>
class CModule
{
public:
    HMODULE m_hModule;
    typedef CModule<Name> type;
    typedef Name          name_type;
    static type &GetModule()
    {
        static type Module;
        return Module;
    }
    ~CModule()
    {
        if (m_hModule)
            FreeLibrary(m_hModule);
    }
private:
    CModule()
    {
        TCHAR szFileName[name_type::name_size];
        name_type::MakeStr(szFileName);
        m_hModule = LoadLibrary(szFileName);
    }
};

template <class Module, class Name, class Proxy>
class CDynFunction
{
public:
    typedef CDynFunction<Module, Name, Proxy> type;
    typedef Proxy                              proxy_type;
    typedef Module                              module_type;
    typedef Name                              name_type;
    
    proxy_type::fun_type m_pfnProxy;
    
    static type &GetProxy()
    {
        static type proxy;
        return proxy;
    }
    static BOOL InitFunction()
    {
        HMODULE hModule = Module::GetModule().m_hModule;
        if (hModule)
        {
            TCHAR szFunName[name_type::name_size];
            name_type::MakeStr(szFunName);
            FARPROC pFunction = GetProcAddress(hModule, szFunName);
            if (pFunction)
            {
                GetProxy().m_pfnProxy = (proxy_type::fun_type)pFunction;
                return TRUE;
            }
        }
        return FALSE;
    }
private:
    CDynFunction():m_pfnProxy(&proxy_type::Proxy<type>::ProxyFun)
    {
    }
};

template<class R, R value = R()>
struct FunProxyValuePolicy
{
    template <class DynFunction> 
    struct Dummy
    {
        static DynFunction::proxy_type::ret_type MakeReturn()
        {
            return value;
        }
    };
};

struct CDynFunException
{
    CDynFunException();
    CDynFunException(LPCTSTR sMessage):m_sMessage(sMessage)
    {
    }
    CDynFunException(const CDynFunException &other):m_sMessage(other.m_sMessage)
    {
    }
    CDynFunException &operator = (const CDynFunException &other)
    {
        m_sMessage = other.m_sMessage;
        return *this;
    }
    CString m_sMessage;
};

template<class E = CDynFunException>
struct FunProxyThrowPolicy
{
    template <class DynFunction> 
    struct Dummy
    {
        static DynFunction::proxy_type::ret_type MakeReturn()
        {
            TCHAR szFunName[DynFunction::name_type::name_size];
            DynFunction::name_type::MakeStr(szFunName);
            CString sMessage;
            sMessage.Format(_T("Can'n load procedure <%s>: %d"), szFunName, GetLastError());
            throw E(sMessage);
            return 0;
        }
    };
};

template <typename R, typename P1, class Policy = FunProxyValuePolicy<R> > struct FunProxy
{
    typedef R (WINAPI *fun_type)(P1);
    typedef R ret_type;
    
    template <class DynFunction> struct Proxy
    {
        static R WINAPI ProxyFun(P1 param)
        {
            if (DynFunction::InitFunction())
                return DynFunction::GetProxy().m_pfnProxy(param);
            return Policy::Dummy<DynFunction>::MakeReturn();
        }
    };
};





#define USE_MODULE_BEGIN(nmspace, NameId) \
namespace nmspace \
{\
    typedef CModule< CNameId< /NameId/ > > module_type;\

#define USE_MODULE_END \
};\


#define DECLARE_FUN_P1(Name, NameId, R, P1)\
R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId< /NameId/ >, FunProxy<R, P1> >::GetProxy().m_pfnProxy;

#define DECLARE_FUN_P1_ERR(Name, NameId, R, P1, E)\
R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId< /NameId/ >, FunProxy<R, P1, FunProxyValuePolicy<R, E> > >::GetProxy().m_pfnProxy;
 
#define DECLARE_FUN_P1_THROW(Name, NameId, R, P1)\
R (WINAPI *&Name)(P1) = CDynFunction<module_type, CNameId< /NameId/ >, FunProxy<R, P1, FunProxyThrowPolicy<> > >::GetProxy().m_pfnProxy;
http://www.rusyaz.ru/pr — стараемся писАть по-русски
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.