如何在Microsoft SAPI中使用SetNotifyCallbackFunction()?

时间:2016-02-15 05:17:49

标签: c++ callback sapi

我正在使用Microsoft Speech API,但我很难理解其中一个功能。该函数名为SetNotifyCallbackFunction(),它是ISpNotifySource的一部分。我遇到的问题是第一个参数是回调函数。我在MSDN或在线示例中找不到这样的示例。第一个参数的类型为SPNOTIFYCALLBACK,我可以在网上找到很少的信息。我已经尝试声明一个名为testCallback()的函数,但我一直收到一条错误,指出第一个参数必须是SPNOTIFYCALLBACK类型。

#include "stdafx.h"
#include<sphelper.h>
#include <sapi.h>

int main() {

    RESULT hr = S_OK;
    CComPtr<ISpRecoContext> g_cpRecoCtxt;

    hr = g_cpRecoCtxt->SetNotifyCallbackFunction(testCallback, NULL, NULL);

}

void testCallback() {
// Some code here..
}

有谁知道如何实现回调,以便我可以使用SetNotifyCallbackFunction()

1 个答案:

答案 0 :(得分:1)

我对你问题中上面评论中列出的github采取了一个看法,它似乎比一个简单的一次性测试程序真正需要的复杂一点。另外,如果您要实现一个包含所有COM指针的类,您可能不希望使用SetNotifyCallbackFunction,而是让您的类实现SetNotifyCallbackInterface。

#include <sapi.h>
#include <sphelper.h>
#include <conio.h>

CComPtr<ISpRecognizer> g_cpEngine;
CComPtr<ISpRecoContext> g_cpContext;
CComPtr<ISpRecoGrammar> g_cpGrammar;

void __stdcall testCallback(WPARAM wParam, LPARAM lParam) {
    CSpEvent evt;
    ISpRecoResult* pPhrase;
    LPWSTR *text;
    bool exit = false;
    //text = new LPWSTR(L"");
    HANDLE waitHandle = NULL;
    waitHandle = g_cpContext->GetNotifyEventHandle();
    do{
        WaitForSingleObject(waitHandle, INFINITE);
        while (g_cpContext != NULL && evt.GetFrom(g_cpContext) == S_OK)
        {
        // Look at recognition event only
            switch (evt.eEventId)
            {
                case SPEI_RECOGNITION:
                    pPhrase = evt.RecoResult();
                    text = new LPWSTR(L"");
                    pPhrase->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, text, NULL);

                    wprintf(L"%ls\n", *text);
                    if(wcscmp(L"Exit",*text) == 0){
                        exit = true;
                    }
                    delete[] text;
                break;

                case SPEI_FALSE_RECOGNITION:
                    wprintf(L"False Reco\n");
                break;
            }
        }

    }while(!exit && g_cpContext != NULL);
    if(g_cpEngine)
        g_cpEngine->SetRecoState(SPRECOSTATE::SPRST_INACTIVE);
}

int main(int argc, char* argv[]){
    HRESULT hr = S_OK;
    HANDLE waitHandle;
    ULONGLONG ullEvents;
    DWORD dwRetVal;
    HANDLE thread;
    ullEvents = SPFEI(SPEI_RECOGNITION) | SPFEI(SPEI_FALSE_RECOGNITION);
    waitHandle = NULL;

    dwRetVal = 0;
    ::CoInitialize(NULL);
    hr = g_cpEngine.CoCreateInstance(CLSID_SpSharedRecognizer);
    hr = g_cpEngine->CreateRecoContext( &g_cpContext );
    hr = g_cpContext->SetAudioOptions(SPAO_NONE, NULL, NULL);
    hr = g_cpContext->CreateGrammar(NULL,&g_cpGrammar);
    hr = g_cpContext->SetInterest(ullEvents,ullEvents);
    hr = g_cpContext->SetNotifyCallbackFunction(testCallback, NULL, NULL);
    hr = g_cpGrammar->SetDictationState(SPRULESTATE::SPRS_ACTIVE);
    hr = g_cpEngine->SetRecoState(SPRECOSTATE::SPRST_ACTIVE);

    thread = ::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)testCallback,NULL,NULL,NULL);

    puts("Press any key to continue...");
    getch();

    g_cpGrammar.Release();
    g_cpContext.Release();
    g_cpEngine.Release();
    ::CoUninitialize();
    return 0;
}

这个程序没有错误处理,请注意,它使用getch()来防止它退出和清理。在处理来自识别器的事件时,您必须找到自己的方法来保持程序繁忙。