次の方法で共有


コールバックの登録

状態変数の値が変更されたとき、またはそれが表すサービス インスタンスが使用できなくなったときにアプリケーションに通知が必要な場合、アプリケーションはコールバック関数を登録する必要があります。 呼び出すサービス オブジェクトのコールバック関数を登録するには、 IUPnPService::AddCallback メソッドを 使用します。 このメソッドを使用して、複数のコールバックを登録できます。

開発者は、非同期コールバック内で非同期操作を取り消さないでください。

Note

Visual Basic でのコールバックの追加は、VBScript で使用されるメソッドとは異なります。 VBScript で使用される GetRef 関数は、Visual Basic では使用できません。 したがって、開発者は、既定のメソッドとしてコールバック関数を持つ IDispatch オブジェクトを作成する必要があります。 「Visual Basic でのコールバックの登録」を参照してください。

 

VBScript の例

次の VBScript コードでは、状態変数の値が変更されたとき、またはサービス インスタンスが使用できなくなったときに呼び出されるコールバック関数 serviceChangeCallback を定義します。 関数には 4 つの引数があります。

関数の最初の引数は、コールバックが呼び出される理由を指定します。 状態変数が変更されたか、サービス インスタンスが使用できなくなったために呼び出されます。

2 番目の引数は、コールバックが呼び出される Service オブジェクトです。 状態変数の変更に対してコールバックが呼び出された場合、関数には、変更された変数の名前とその新しい値という 2 つの追加の引数が渡されます。

この例では、コールバックは、変更された変数の名前とその新しい値を示すメッセージ ボックスを表示し、状態変数の変更に対してコールバックが呼び出された場合に表示します。 それ以外の場合は、サービス インスタンスが使用できなくなったことを示すメッセージが表示されます。

コード フラグメントの最後の部分は、 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;
}