콜백 등록
상태 변수의 값이 변경되거나 표시되는 instance 서비스를 사용할 수 없게 될 때 애플리케이션에 알림이 필요한 경우 애플리케이션은 콜백 함수를 등록해야 합니다. 호출할 서비스 개체에 대한 콜백 함수를 등록하려면 IUPnPService::AddCallback 메서드를 사용합니다. 이 메서드는 둘 이상의 콜백을 등록하는 데 사용할 수 있습니다.
개발자는 비동기 콜백 내에서 비동기 작업을 취소해서는 안 됩니다.
참고
Visual Basic에서 콜백을 추가하는 것은 VBScript에서 사용되는 메서드와 다릅니다. VBScript에서 사용되는 GetRef 함수는 Visual Basic에서 사용할 수 없습니다. 따라서 개발자는 콜백 함수를 기본 메서드로 사용하는 IDispatch 개체를 만들어야 합니다. Visual Basic에서 콜백 등록을 참조하세요.
VBScript 예제
다음 VBScript 코드는 상태 변수 값이 변경되거나 서비스 instance 사용할 수 없게 될 때 호출할 콜백 함수 serviceChangeCallback을 정의합니다. 함수에는 4개의 인수가 있습니다.
함수에 대한 첫 번째 인수는 콜백이 호출되는 이유를 지정합니다. 상태 변수가 변경되었거나 서비스 instance 사용할 수 없게 되었기 때문에 호출됩니다.
두 번째 인수는 콜백이 호출되는 Service 개체입니다. 상태 변수 변경에 대해 콜백이 호출되면 함수는 변경된 변수의 이름과 새 값이라는 두 개의 추가 인수를 전달합니다.
이 예제에서 콜백은 변경된 변수의 이름과 새 값을 보여 주는 메시지 상자와 상태 변수 변경에 대한 콜백이 호출된 경우를 표시합니다. 그렇지 않으면 서비스 instance 더 이상 사용할 수 없음을 나타내는 메시지가 표시됩니다.
코드 조각의 마지막 부분은 AddCallback 메서드를 사용하여 콜백 함수를 등록하는 방법을 보여줍니다. 서비스 개체 변수인 appService 및 xportService 는 서비스 개체 가져오기에 표시된 대로 초기화된 것으로 간주됩니다.
'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;
}