105 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
///////////////////////////////////////////////////////////////////////////////
 | 
						|
// Name:        wx/msw/wrl/event.h
 | 
						|
// Purpose:     WRL event callback implementation
 | 
						|
// Author:      nns52k
 | 
						|
// Created:     2021-02-25
 | 
						|
// Copyright:   (c) 2021 wxWidgets team
 | 
						|
// Licence:     wxWindows licence
 | 
						|
///////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
#ifndef _WX_MSW_PRIVATE_WRL_H_
 | 
						|
#define _WX_MSW_PRIVATE_WRL_H_
 | 
						|
 | 
						|
#include <atomic>
 | 
						|
 | 
						|
template <typename baseT, typename ...argTs>
 | 
						|
class CInvokable : public baseT
 | 
						|
{
 | 
						|
public:
 | 
						|
    CInvokable() : m_nRefCount(0) {}
 | 
						|
    virtual ~CInvokable() {}
 | 
						|
    // IUnknown methods
 | 
						|
    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObj) override
 | 
						|
    {
 | 
						|
        if (riid == __uuidof(baseT) || riid == IID_IUnknown)
 | 
						|
        {
 | 
						|
            *ppvObj = this;
 | 
						|
            AddRef();
 | 
						|
            return S_OK;
 | 
						|
        }
 | 
						|
 | 
						|
        *ppvObj = NULL;
 | 
						|
        return E_NOINTERFACE;
 | 
						|
    }
 | 
						|
    ULONG STDMETHODCALLTYPE AddRef() override
 | 
						|
    {
 | 
						|
        return ++m_nRefCount;
 | 
						|
    }
 | 
						|
    ULONG STDMETHODCALLTYPE Release() override
 | 
						|
    {
 | 
						|
        size_t ret = --m_nRefCount;
 | 
						|
        if (ret == 0)
 | 
						|
            delete this;
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
private:
 | 
						|
    std::atomic<size_t> m_nRefCount;
 | 
						|
};
 | 
						|
 | 
						|
template <typename baseT, typename ...argTs>
 | 
						|
class CInvokableLambda : public CInvokable<baseT, argTs...>
 | 
						|
{
 | 
						|
public:
 | 
						|
    CInvokableLambda(std::function<HRESULT(argTs...)> lambda)
 | 
						|
        : m_lambda(lambda)
 | 
						|
    {}
 | 
						|
    // baseT method
 | 
						|
    HRESULT STDMETHODCALLTYPE Invoke(argTs ...args) override
 | 
						|
    {
 | 
						|
        return m_lambda(args...);
 | 
						|
    }
 | 
						|
private:
 | 
						|
    std::function<HRESULT(argTs...)> m_lambda;
 | 
						|
};
 | 
						|
 | 
						|
template <typename baseT, typename contextT, typename ...argTs>
 | 
						|
class CInvokableMethod : public CInvokable<baseT, argTs...>
 | 
						|
{
 | 
						|
public:
 | 
						|
    CInvokableMethod(contextT* ctx, HRESULT(contextT::* mthd)(argTs...))
 | 
						|
        : m_ctx(ctx), m_mthd(mthd)
 | 
						|
    {}
 | 
						|
    // baseT method
 | 
						|
    HRESULT STDMETHODCALLTYPE Invoke(argTs ...args) override
 | 
						|
    {
 | 
						|
        return (m_ctx->*m_mthd)(args...);
 | 
						|
    }
 | 
						|
private:
 | 
						|
    contextT* m_ctx;
 | 
						|
    HRESULT(contextT::* m_mthd)(argTs...);
 | 
						|
};
 | 
						|
 | 
						|
// the function templates to generate concrete classes from above class templates
 | 
						|
template <
 | 
						|
    typename baseT, typename lambdaT, // base type & lambda type
 | 
						|
    typename LT, typename ...argTs // for capturing argument types of lambda
 | 
						|
>
 | 
						|
wxCOMPtr<baseT> Callback_impl(lambdaT&& lambda, HRESULT(LT::*)(argTs...) const)
 | 
						|
{
 | 
						|
    return wxCOMPtr<baseT>(new CInvokableLambda<baseT, argTs...>(lambda));
 | 
						|
}
 | 
						|
 | 
						|
template <typename baseT, typename lambdaT>
 | 
						|
wxCOMPtr<baseT> Callback(lambdaT&& lambda)
 | 
						|
{
 | 
						|
    return Callback_impl<baseT>(std::move(lambda), &lambdaT::operator());
 | 
						|
}
 | 
						|
 | 
						|
template <typename baseT, typename contextT, typename ...argTs>
 | 
						|
wxCOMPtr<baseT> Callback(contextT* ctx, HRESULT(contextT::* mthd)(argTs...))
 | 
						|
{
 | 
						|
    return wxCOMPtr<baseT>(new CInvokableMethod<baseT, contextT, argTs...>(ctx, mthd));
 | 
						|
}
 | 
						|
 | 
						|
#endif // _WX_MSW_PRIVATE_WRL_H_
 |