Events 在C++中使用非静态委托属性函数作为参数 我在C++中制作了一个接口类,用于语音识别,我使用尤利乌斯API…p>

Events 在C++中使用非静态委托属性函数作为参数 我在C++中制作了一个接口类,用于语音识别,我使用尤利乌斯API…p>,events,properties,static,delegates,c++-cli,Events,Properties,Static,Delegates,C++ Cli,我的类有一些事件,这些事件将由Julius API触发。 Julius API的函数调用callback_add具有以下签名: int callback_add Recog*Recog,int code,void*funcRecog*Recog,void*数据,void数据 我使用一些“代理”函数来调用事件,并将这些函数传递给callback\u add 如果属性事件是静态的,则可以正常工作,但如果是非静态的,则在代理函数中无法识别该属性 困难是因为我必须使用callback_add函数,不能修

我的类有一些事件,这些事件将由Julius API触发。 Julius API的函数调用callback_add具有以下签名:

int callback_add Recog*Recog,int code,void*funcRecog*Recog,void*数据,void数据

我使用一些“代理”函数来调用事件,并将这些函数传递给callback\u add

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

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

下面是该类的摘要,包含两个事件:静态事件和非静态事件

标题

来源

问题发生在StartOnEngineStart函数中:


错误C2227:“->GetInvocationList”的左侧必须指向class/struct/union/generic type

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

尝试使用伪参数传递实例。但是要小心,因为垃圾收集器会移动对象,除非您固定了它们,所以简单地传递地址是不起作用的。您需要创建并传递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());

}

许可证要求不多,但如果您使用它,请确保遵守这些要求。

这是我的担心。我对C++很生疏,现在我使用Java和C。你能帮我举个例子吗?你认为我使用的是事件而不是属性吗?我如何传递这个实例,在数据参数为void时添加一个回调*??@Fabio:对于本机类,很简单,你只需将指针传递到对象,然后在回调中静态地将其转换。对于托管对象,最好的做法是创建一个内部带有gcroot的本机类,然后传递指向本机对象的指针。然后回调可以从本机对象中获取托管句柄。@Fabio:我添加了一个基本完整的示例。
#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);
    }
}
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());

}