0

我在 C++ 中创建了一个用于语音识别的接口类,我正在使用 Julius API。http://julius.sourceforge.jp/en_index.php?q=index-en.html

好吧,我的班级有一些事件,这些事件将由 Julius API 触发。Julius API 具有带有此签名的函数调用 callback_add:

int callback_add (Recog *recog, int code, void(*func)(Recog *recog, void *data), void data)

我使用一些“代理”函数来调用事件并将这些函数传递给 callback_add。

如果属性事件是静态的,它可以正常工作,但如果是非静态的,则在代理函数内部无法识别该属性。

困难是因为我必须使用 callback_add 函数并且不能修改它。

这是具有 2 个事件(静态和非静态)的类的摘要

标题

#ifndef FALAENGINE_H_
#define FALAENGINE_H_

#pragma once

extern "C"{
#include <julius/julius.h>
}

namespace FalaAPI {

    public ref class FalaEngine
    {
    public:
        FalaEngine();
        ~FalaEngine();

        // Events
        delegate void OnRecognizedDele(FalaAPI::RecoResult^ result);
        static property OnRecognizedDele^ OnRecognized;

        delegate void OnEngineStartDele();
        property OnEngineStartDele^ OnEngineStart;

    private:
        Recog *recog;
        Jconf *jconf;
    };
}

#endif /* FALAENGINE_H_*/

来源

#include "stdafx.h"

using System::String;
using System::Console;

#include "FalaEngine.h"
#include <windows.h>

namespace FalaAPI{
    void StartOnEngineStart()(Recog *recog, void * dummy){
        if(FalaEngine::OnEngineStart->GetInvocationList()->Length > 0)
            FalaEngine::OnEngineStart->Invoke();
    }

    void StartOnRecognized()(Recog *recog, void * dummy){
        if(FalaEngine::OnRecognized->GetInvocationList()->Length > 0)
            FalaEngine::OnRecognized->Invoke();
    }

    FalaEngine::FalaEngine(){
        recog = j_recog_new();
        jconf = j_jconf_new();

        //Julius callback Functions
        callback_add(recog, CALLBACK_EVENT_PROCESS_ONLINE, StartOnEngineStart, NULL);

        callback_add(recog, CALLBACK_RESULT, StartOnRecognized, NULL);
    }
}

问题发生在 StartOnEngineStart 函数内部:

错误 C2227:“->GetInvocationList”左侧必须指向类/结构/联合/通用类型

4

1 回答 1

0

一个非静态成员分别存在于每个实例中。您还没有指定哪个实例包含您要检查的委托,您只指定了一个类(并且可能有很多实例)。

尝试使用dummy参数来传递您的实例。但要小心,因为垃圾收集器会移动对象,除非你已经固定它们,所以简单地传递地址是行不通的。您需要创建并传递 a GCHandle。(注意不要泄露 GCHandle,否则你的对象永远不会被释放)


像这样的东西应该是有效的:

ref class FalaEngine;

struct EngineHandle
{
    gcroot<FalaEngine^> handle;
    EngineHandle(FalaEngine^ engine) : handle(engine) {}
};

public ref class FalaEngine
{
    clr_scoped_ptr<EngineHandle> callback_ptr;
public:
    FalaEngine();
    ~FalaEngine();

    // Events
    delegate void OnRecognizedDele(FalaAPI::RecoResult^ result);
    property OnRecognizedDele^ OnRecognized;


    delegate void OnEngineStartDele();
    property OnEngineStartDele^ OnEngineStart;

private:
    Recog *recog;
    Jconf *jconf;
};

void StartOnEngineStart(Recog *recog, void * dummy)
{
    FalaEngine^ that = static_cast<EngineHandle*>(dummy)->handle;
    that->OnEngineStart(); // C++/CLI already checks if the invocation list is empty
}


void StartOnRecognized(Recog *recog, void * dummy)
{
    FalaEngine^ that = static_cast<EngineHandle*>(dummy)->handle;
    that->OnRecognized(recog->get_result());
}

FalaEngine::FalaEngine()
    : callback_ptr(new EngineHandle(this))
{
    recog = j_recog_new();
    jconf = j_jconf_new();


    //Julius callback Functions
    callback_add(recog, CALLBACK_EVENT_PROCESS_ONLINE, StartOnEngineStart, callback_ptr.get());

    callback_add(recog, CALLBACK_RESULT, StartOnRecognized, callback_ptr.get());

}

课堂在clr_scoped_ptr这里。 许可证要求并不多,但如果您使用它,请确保遵循它们。

于 2012-06-30T14:27:23.323 回答