Inscription d’un rappel
Si l’application nécessite une notification lorsque la valeur d’une variable d’état change ou que le service instance qu’elle représente devient indisponible, l’application doit inscrire une fonction de rappel. Pour inscrire une fonction de rappel pour l’objet de service à appeler, utilisez la méthode IUPnPService::AddCallback . Cette méthode peut être utilisée pour inscrire plusieurs rappels.
Les développeurs ne doivent pas annuler une opération asynchrone à l’intérieur d’un rappel asynchrone.
Notes
L’ajout d’un rappel en Visual Basic est différent de la méthode utilisée dans VBScript. La fonction GetRef utilisée dans vbScript n’est pas disponible en Visual Basic. Par conséquent, un développeur doit créer un objet IDispatch qui a la fonction de rappel comme méthode par défaut. Consultez Inscription d’un rappel en Visual Basic.
Exemple VBScript
Le code VBScript suivant définit la fonction de rappel serviceChangeCallback, à appeler lorsque les valeurs des variables d’état changent ou lorsque le service instance devient indisponible. La fonction a quatre arguments.
Le premier argument de la fonction spécifie la raison pour laquelle le rappel est appelé. Elle est appelée soit parce qu’une variable d’état a changé, soit parce que le service instance est devenu indisponible.
Le deuxième argument est l’objet Service pour lequel le rappel est appelé. Si le rappel est appelé pour une modification de variable d’état, la fonction reçoit deux arguments supplémentaires : le nom de la variable qui a changé et sa nouvelle valeur.
Dans cet exemple, le rappel affiche simplement une boîte de message qui affiche le nom de la variable modifiée et sa nouvelle valeur, et si le rappel a été appelé pour une modification de variable d’état. Sinon, il affiche un message indiquant que le service instance n’est plus disponible.
La dernière partie du fragment de code montre comment inscrire la fonction de rappel à l’aide de la méthode AddCallback . Les variables d’objet de service, appService et xportService sont supposées avoir été initialisées comme indiqué dans Obtention d’objets de service.
'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")
Exemple 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;
}