다음을 통해 공유


콜백 등록

상태 변수의 값이 변경되거나 표시되는 instance 서비스를 사용할 수 없게 될 때 애플리케이션에 알림이 필요한 경우 애플리케이션은 콜백 함수를 등록해야 합니다. 호출할 서비스 개체에 대한 콜백 함수를 등록하려면 IUPnPService::AddCallback 메서드를 사용합니다. 이 메서드는 둘 이상의 콜백을 등록하는 데 사용할 수 있습니다.

개발자는 비동기 콜백 내에서 비동기 작업을 취소해서는 안 됩니다.

참고

Visual Basic에서 콜백을 추가하는 것은 VBScript에서 사용되는 메서드와 다릅니다. VBScript에서 사용되는 GetRef 함수는 Visual Basic에서 사용할 수 없습니다. 따라서 개발자는 콜백 함수를 기본 메서드로 사용하는 IDispatch 개체를 만들어야 합니다. Visual Basic에서 콜백 등록을 참조하세요.

 

VBScript 예제

다음 VBScript 코드는 상태 변수 값이 변경되거나 서비스 instance 사용할 수 없게 될 때 호출할 콜백 함수 serviceChangeCallback을 정의합니다. 함수에는 4개의 인수가 있습니다.

함수에 대한 첫 번째 인수는 콜백이 호출되는 이유를 지정합니다. 상태 변수가 변경되었거나 서비스 instance 사용할 수 없게 되었기 때문에 호출됩니다.

두 번째 인수는 콜백이 호출되는 Service 개체입니다. 상태 변수 변경에 대해 콜백이 호출되면 함수는 변경된 변수의 이름과 새 값이라는 두 개의 추가 인수를 전달합니다.

이 예제에서 콜백은 변경된 변수의 이름과 새 값을 보여 주는 메시지 상자와 상태 변수 변경에 대한 콜백이 호출된 경우를 표시합니다. 그렇지 않으면 서비스 instance 더 이상 사용할 수 없음을 나타내는 메시지가 표시됩니다.

코드 조각의 마지막 부분은 AddCallback 메서드를 사용하여 콜백 함수를 등록하는 방법을 보여줍니다. 서비스 개체 변수인 appServicexportService서비스 개체 가져오기에 표시된 대로 초기화된 것으로 간주됩니다.

'State Change Callback Function
 
'Note:  In the sub declaration statement below, VARIABLE_UPDATE
'is one of two possible values for the callbackType argument; 
'the other is SERVICE_INSTANCE_DIED

Sub serviceChangeCallback(callbacktype, svcObj, varName, value)
    If (callbacktype = "VARIABLE_UPDATE") then
        Dim outString
        outString = "State Variable Changed:" & vbCrLf
        outString = outString & varName & " == " & value
    
        MsgBox(outString, "Service Callback")
    Else if (callbacktype = "SERVICE_INSTANCE_DIED") then
        MsgBox("Service instance is no longer available", 
               "Service Callback")
    End If
End Sub

' ...
    
'Add our state change callback to each service
appService.AddCallback GetRef("serviceChangeCallback")
xportService.AddCallback GetRef("serviceChangeCallback")

C++ 예제

#include <windows.h>
#include <upnp.h>
#include <stdio.h>

#pragma comment(lib, "oleaut32.lib")

class CUPnPServiceCallback : public IUPnPServiceCallback
{
public:
    CUPnPServiceCallback()
    {
        m_lRefCount = 0;
    };
    
    STDMETHODIMP QueryInterface(REFIID iid, LPVOID* ppvObject)
    {
        HRESULT hr = S_OK;
        
        if(NULL == ppvObject)
        {
            hr = E_POINTER;
        }
        else
        {
            *ppvObject = NULL;
        }
        
        if(SUCCEEDED(hr))
        {
            if(IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IUPnPServiceCallback))
            {
                *ppvObject = static_cast<IUPnPServiceCallback*>(this);
                AddRef();
            }
            else
            {
                hr = E_NOINTERFACE;
            }
        }
        
        return hr;
    };
    
    STDMETHODIMP_(ULONG) AddRef()
    {
        return ::InterlockedIncrement(&m_lRefCount);
    };
    
    STDMETHODIMP_(ULONG) Release()
    {
        LONG lRefCount = ::InterlockedDecrement(&m_lRefCount);
        if(0 == lRefCount)
        {
            delete this;
        }
        
        return lRefCount;
    };
    
    STDMETHODIMP StateVariableChanged(IUPnPService *pus, LPCWSTR pcwszStateVarName, VARIANT varValue)
    {
        HRESULT    hr = S_OK;
        BSTR ServiceId;
        hr = pus->get_Id(&ServiceId);
        if (SUCCEEDED(hr))
        {
            VARIANT AlphaVariant;
            VariantInit(&AlphaVariant);
            hr = VariantChangeType(&AlphaVariant, &varValue, VARIANT_ALPHABOOL, VT_BSTR);
            if(SUCCEEDED(hr))
            {
                printf("StateVariableChanged called for the %S service"
                       " for %S state variable with the value=%S.\n",
                        ServiceId, pcwszStateVarName, V_BSTR(&AlphaVariant));
                VariantClear(&AlphaVariant);
            }
            SysFreeString(ServiceId);
        }
        return hr;
    };

    STDMETHODIMP ServiceInstanceDied(IUPnPService *pus)
    {
        HRESULT hr = S_OK;
        BSTR ServiceType;
        hr = pus->get_ServiceTypeIdentifier(&ServiceType);
        if(SUCCEEDED(hr))
        {
            printf("ServiceInstanceDied called for the %S service!\n", ServiceType);
            SysFreeString(ServiceType);
        }
        return hr;
    };
    
private:
    LONG m_lRefCount;
    
};

HRESULT AddCallbackToService(IUPnPService* pUPnPService)
{
    HRESULT hr = S_OK;

    IUnknown* pUPnPServiceCallback = new CUPnPServiceCallback;
    if(NULL != pUPnPServiceCallback)
    {
        pUPnPServiceCallback->AddRef();
        hr = pUPnPService->AddCallback(pUPnPServiceCallback);
        pUPnPServiceCallback->Release();
    }
    else
    {
        hr = E_OUTOFMEMORY;
    }
    return hr;
}