2012-06-06 4 views
5

이벤트로 C# COM 개체를 만들 수있었습니다. 아래 코드를 찾으십시오.C++에서 C# COM 이벤트 처리

[Guid("1212674-38748-45434")] 
    public interface ICalculator 
    { 
     int Add(int Num1, int Num2); 
    } 

    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
    [Guid("3453674234-84444-84784")] 
    public interface ICalculatorEvents 
    { 
     [DispId(1)] 
     void Completed(int Result); 
    } 

    [ClassInterface(ClassInterfaceType.None)] 
    [ComSourceInterfaces(typeof(ICalculatorEvents))] 
    [Guid("87457845-945u48-4954")] 
    public class Calculator : ICalculator 
    { 
     public delegate void CompletedDelegate(int result); 
     public event CompletedDelegate Completed; 
     public Add(int Num1, int Num2) 
     { 
      int Result = Num1 + Num2; 
      if(Completed != null) 
       Completed(Result); 
     } 
    } 

이 COM 개체를 C++ 콘솔 응용 프로그램에서 가져오고 'Add()'메서드를 호출 할 수 있습니다. 내 C++ 응용 프로그램에서 'Completed'이벤트를 처리하는 방법을 잘 모르겠습니다. 이것에 대해 조언 해 주시겠습니까? 이 이벤트가 발생할 때마다 콘솔에 결과 값을 표시하려고합니다.

아래의 C++ 응용 프로그램 코드를 찾으십시오. 'Completed'이벤트는 결코 여기서 처리되지 않습니다. 이것은 무한 루프로 진행됩니다.

#import "Calculator.tlb" 
    using namespace Calculator; 
    int Flag = 0; 
    class HandleEvent : public ICalculatorEvent 
    { 
     public: 
      HandleEvent(void); 
      ~HandleEvent(void); 
      HRESULT __stdcall QueryInterface(const IID &, void **); 
      ULONG __stdcall AddRef(void) { return 1; } 
      ULONG __stdcall Release(void) { return 1; } 
      HRESULT __stdcall Completed(int Result); 
    }; 

    HandleEvent::HandleEvent(void) 
    { 
    } 

    HRESULT HandleEvent::Completed(int Result) 
    { 
     printf("Addition Completed, Result: %d", Result); 
     Flag = 1; 
    } 

    HRESULT HandleEvent::QueryInterface(const IID & iid,void ** pp) 
    { 
     if (iid == __uuidof(ICalculatorEvent) || iid == __uuidof(IUnknown)) 
     { 
      *pp = this; 
      AddRef(); 
      return S_OK; 
     } 
     return E_NOINTERFACE; 
    } 

    int _tmain(int argc, _TCHAR* argv[]) 
    { 
     CoInitialize(NULL); 
     Flag = 0; 
     ICalculatorPtr pCalc(__uuidof(Calculator)); 
     pCalc->Add(5, 6); 

     do 
     { 
     }while(Flag == 0); 

     CoUninitialize(); 
     return 0; 
    } 

미리 감사드립니다.

+0

나는 항상 널 (null)이므로 완료 이벤트 객체가 호출되지 것이라 생각합니다. ICalculatorEvents 인터페이스가 구현되는 클래스는 무엇입니까? –

+0

ICalculatorEvents는 C++ 응용 프로그램에서 구현됩니다. 아래의 C++ 코드를 찾으십시오. – GeekCandy

+0

C++ 코드는 어디에 있습니까? –

답변

0

대리인을 사용하려면 인터페이스를 선언 할 필요가 없습니다. 다음과 같이 _tmain() 함수를 변경하십시오.

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    CoInitialize(NULL); 
    Flag = 0; 

    EventHandler evh ; 
    ICalculatorPtr pCalc(__uuidof(Calculator)); 
    pCalc->Completed = &evh.Completed() ; 
    pCalc->Add(5, 6); 

    do 
    { 
    }while(Flag == 0); 

    CoUninitialize(); 
    return 0; 
} 

인터페이스를 사용하려면이 방법을 사용하십시오.

[ClassInterface(ClassInterfaceType.None)] 
[ComSourceInterfaces(typeof(ICalculatorEvents))] 
[Guid("87457845-945u48-4954")] 
public class Calculator : ICalculator 
{ 
    public ICalculatorEvents callbackObject ; 

    public Add(int Num1, int Num2) 
    { 
     int Result = Num1 + Num2; 
     if(callbackObject != null) 
      callbackObject.Completed(Result); 
    } 
} 

으로 변경하고 이에 대한 _tmain() 메소드를 변경하십시오.

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    CoInitialize(NULL); 
    Flag = 0; 

    EventHandler evh ; 
    ICalculatorPtr pCalc(__uuidof(Calculator)); 
    pCalc->callbackObject = &evh ; 
    pCalc->Add(5, 6); 

    do 
    { 
    }while(Flag == 0); 

    CoUninitialize(); 
    return 0; 
} 
0

내가 C에서 # 비동기 이벤트 처리를 위해

CoInitializeEx(NULL, COINIT_MULTITHREADED); 

을 사용하여 수행 할 수 있어야 C++ 클라이언트에서 해당 COM 초기화를 발견 (.NET) COM 서버, 그렇지 않으면 C++는 클라이언트는 CoUninitialize() 호출 후 이벤트를 수신 .

이벤트 처리 클래스 :

class EventWrapper : public IDispEventSimpleImpl<1, EventWrapper, &DIID_RumCardCOMEvents > 
    { 
    public: 
     // now you need to declare a sink map - a map of methods handling the events 
     BEGIN_SINK_MAP(EventWrapper) 
      SINK_ENTRY_INFO(1, DIID_RumCardCOMEvents, 0x1, isCardInserted, &cardInserted) 
      SINK_ENTRY_INFO(1, DIID_RumCardCOMEvents, 0x2, isCardRemoved, &cardRemoved) 
      // event interface id (can be more than 1)---+  |  |     | 
      // must match dispid of your event -----------------+  |     | 
      // method which handles the event ------------------------+     | 
      // type information for event, see below --------------------------------------+ 
     END_SINK_MAP() 

    // declare the type info object. You will need one for each method with different signature. 
     // it will be defined in the .cpp file, as it is a static member 
     static _ATL_FUNC_INFO cardInserted; // 'placeholder' object to carry event information (see below) 
     static _ATL_FUNC_INFO cardRemoved; // 'placeholder' object to carry event information (see below) 

     // method which handles the event 
     STDMETHOD (isCardInserted)(unsigned char type) 
     { 
      // usually it is defined it in the .cpp file 
      cout << "isCardInserted: " << (int)type << endl; 
      return 0; 
     } 

     STDMETHOD (isCardRemoved)() 
     { 
      // usually it is defined it in the .cpp file 
      cout << "isCardRemoved" << endl; 
      return 0; 
     } 
    }; 

홈페이지 :

int main() 
    { 
     CoInitializeEx(NULL, COINIT_MULTITHREADED); 
     try 
     { 
      EventWrapper ev; 
      ev.DispEventAdvise(/*COM interface*/); 
      // receiving events 
      ev.DispEventUnadvise(/*COM interface*/); 
     } 
     catch (_com_error& e) 
     { 
      cout << "Exception: " << e.ErrorMessage() << endl; 
     } 

     CoUninitialize(); 
     return 0; 
    }