在C ++ / CLI中将非静态委托属性函数作为参数传递

时间:2012-06-30 14:08:14

标签: events properties static delegates c++-cli

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

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

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

我使用一些'proxy'函数来调用事件并将这些函数传递给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:' - &gt; GetInvocationList'的左侧必须指向class / struct / union / generic类型

1 个答案:

答案 0 :(得分:0)

非静态成员在每个实例中单独存在。您尚未指定哪个实例包含您要检查的委托,您只指定了一个类(并且可能有许多实例)。

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

}

The clr_scoped_ptr class is here.许可证要求不多,请确保在使用时遵循这些要求。