1

我是 COM 编程的新手。

我有大问题。我正在尝试通过 COM 服务器处理来自 CANoe 应用程序的事件。首先,我尝试在本机 C++ 中执行此操作,但没有结果。现在我正在尝试使用 ATL。我做错了什么,但我不知道是什么。当事件发生时,我的客户端应用程序会暂停自身和 CANoe。关闭客户端应用程序后,CANoe 工作正常。所以我知道我的客户端应用程序处理来自 CANoe 的事件,但它不能提供它。我的源代码中的代码注释部分也被使用,但结果相同。

#import "CANoe.tlb" //importing CANoe type library
#include "stdafx.h"
#include <atlbase.h> //COM Server methods
#include <iostream>
#include <atlhost.h>

using namespace CANoe;
using namespace std;

_ATL_FUNC_INFO infoZero = { CC_STDCALL, VT_EMPTY, 0, 0};
_ATL_FUNC_INFO infoOne = { CC_STDCALL, VT_EMPTY, 1, { VT_I4 } };

class CANoeComClient : 
    //IDispEventSimpleImpl<1, CANoeComClient, &__uuidof(_IMeasurementEvents)>,
    //IDispEventSimpleImpl<2, CANoeComClient, &__uuidof(_IEnvironmentVariableEvents)>
    IDispEventSimpleImpl<1, CANoeComClient, &__uuidof(_IApplicationEvents)>
{
    IApplicationPtr pApp; //Pointer to the Application Object
    IMeasurementPtr pMeasure; //Pointer to the Measurement object
    _IMeasurementEventsPtr pMEvent; //Pointer to the Measurement's Events
    IEnvironmentPtr pEnvironment; //Pointer to the Environment Object
    IEnvironmentVariable2Ptr pEnvironmentVar; //Pointer to the Environment Variable Object
    ICAPL2Ptr pCAPL; //Pointer to the CAPL Object
    CLSID clsid; //globally unique identifier that identifies a COM class object
    HRESULT result; //results of COM functions

public:
    //typedef IDispEventSimpleImpl<2, CANoeComClient, &__uuidof(CANoe::_IEnvironmentVariableEvents)> EnvVarEventsHandler;
    //typedef IDispEventSimpleImpl<1, CANoeComClient, &__uuidof(CANoe::_IMeasurementEvents)> MeasurementEventsHandler;  
    typedef IDispEventSimpleImpl<1, CANoeComClient, &__uuidof(CANoe::_IApplicationEvents)> ApplicationEventsHandler;
    void __stdcall OnStart(void);
    void __stdcall OnStop(void);
    void __stdcall OnOpen(void);
    void __stdcall OnQuit(void);

    BEGIN_SINK_MAP(CANoeComClient)
        //SINK_ENTRY_INFO(1, __uuidof(CANoe::_IMeasurementEvents), 0x02, OnStart, &info)
        //SINK_ENTRY_INFO(1, __uuidof(CANoe::_IMeasurementEvents), 0x03, OnStop, &infoZero)
        SINK_ENTRY_INFO(1, __uuidof(CANoe::_IApplicationEvents), 0x01, OnOpen, &infoZero)
        SINK_ENTRY_INFO(1, __uuidof(CANoe::_IApplicationEvents), 0x02, OnQuit, &infoZero)
    END_SINK_MAP()

    void __stdcall OnChange();
/*
    BEGIN_SINK_MAP(CANoeComClient)
        SINK_ENTRY_INFO(2, __uuidof(CANoe::_IEnvironmentVariableEvents), 0x01, OnChange, &info)
    END_SINK_MAP()*/

    CANoeComClient(_bstr_t configPath);
    HRESULT createEventConnection();
    HRESULT startMeasurement();
    HRESULT stopMeasurement();
};
void CANoeComClient::OnStart()
{
    cout << "kurka wodna 1" << endl;
}
void CANoeComClient::OnStop()
{
    cout << "kurka wodna 2" << endl;
}
void CANoeComClient::OnChange()
{
    cout << "kurka wodna 2" << endl;
}
void CANoeComClient::OnOpen()
{
    cout << "kurka wodna 1" << endl;
}
void CANoeComClient::OnQuit()
{
    cout << "kurka wodna 1" << endl;
}
CANoeComClient::CANoeComClient(_bstr_t configPath)
{
    /* Initialization COM library: */
    if (FAILED(CoInitialize(NULL))) 
    {
        cerr << "Initialization COM Library error" << endl;
        system("pause");
        return;
    }

    /* Actualization clsid variable with CANoe.Application path: */
    if((result = CLSIDFromProgID(L"CANoe.Application", &clsid)) != S_OK) 
    {
        cerr << "Problem with opening application" << endl;
        system("pause");
        return;
    }

    /*Opening CANoe application: */
    result = pApp.CreateInstance(__uuidof(CANoe::Application));
    if(result != S_OK)
    {
        cerr << "pApp fault" << endl;
        return;
    }
    else
        cout << "CANoe opened succesfully" << endl;

    /* Opening CANoe configuration: */
    result = pApp->Open(configPath, FALSE, TRUE); //Opening test.cfg file
    if(result != S_OK)
    {
        cerr << "Opening configuration fault" << endl;
        return;
    }
    else 
        cout << "Configuration loaded succesfully" << endl;

    /*Definitions of all objects: */
    //pMeasure.CreateInstance(__uuidof(CANoe::Measurement));
    pEnvironment = pApp->Environment;
    pEnvironmentVar = pEnvironment->GetVariable(L"env_ClientReq");
    pCAPL = pApp->CAPL;
    result = ApplicationEventsHandler::DispEventAdvise(pApp);
//  result = MeasurementEventsHandler::DispEventAdvise(pMeasure);
    //result = EnvVarEventsHandler::DispEventAdvise(pEnvironmentVar);
    if(result != S_OK)
    {
        cerr << "Creating connection fault" << endl;
        return;
    }
    else 
        cout << "Creating conenction succesfully" << endl;
}

HRESULT CANoeComClient::startMeasurement()
{
    return pMeasure->Start();
}

HRESULT CANoeComClient::stopMeasurement()
{
    return pMeasure->Stop();
}

int _tmain(int argc, _TCHAR* argv[])
{
    int tmp = 0; //temporary variable to used to get envVar values
    HRESULT result; //results of COM functions
    CANoeComClient client(L"C:\\test\\test.cfg");
    while(1);
}

以下是来自 OLE-COM 对象查看器的测量对象和事件的描述:

[
  uuid(CD866FB6-44BF-11D3-8538-00105A3E017B),
  helpstring("Measurement Class")
]
coclass Measurement {
    [default] interface IMeasurement2;
    [default, source] dispinterface _IMeasurementEvents;
};

 [
  odl,
  uuid(A844C1E0-F5CE-11D3-8612-00105A3E017B),
  helpstring("IMeasurement2 Interface"),
  dual,
  oleautomation
]
interface IMeasurement2 : IMeasurement {
    [id(0x0000000a), propget, helpstring("property Running")]
    HRESULT Running([out, retval] VARIANT_BOOL* pVal);
};

[
  uuid(A844C1E0-F5CE-11D3-8612-00105A3E017B),
  helpstring("IMeasurement2 Interface"),
  dual
]
dispinterface IMeasurement2 {
    properties:
    methods:
        [id(0x00000001), propget, helpstring("property Application")]
        IDispatch* Application();
        [id(0x00000002), propget, helpstring("property Parent")]
        IDispatch* Parent();
        [id(0x00000003), helpstring("method Start")]
        void Start();
        [id(0x00000004), helpstring("method Stop")]
        void Stop();
        [id(0x00000005), helpstring("method Step")]
        void Step();
        [id(0x00000006), helpstring("method Animate")]
        void Animate();
        [id(0x00000007), helpstring("method Break")]
        void Break();
        [id(0x00000008), helpstring("method Reset")]
        void Reset();
        [id(0x00000009), propget, helpstring("property AnimationDelay")]
        long AnimationDelay();
        [id(0x00000009), propput, helpstring("property AnimationDelay")]
        void AnimationDelay([in] long rhs);
        [id(0x0000000a), propget, helpstring("property Running")]
        VARIANT_BOOL Running();
};

[
  uuid(CD866FB7-44BF-11D3-8538-00105A3E017B),
  helpstring("_IMeasurementEvents Interface")
]
dispinterface _IMeasurementEvents {
    properties:
    methods:
        [id(0x00000001), helpstring("method OnInit")]
        HRESULT OnInit();
        [id(0x00000002), helpstring("method OnStart")]
        HRESULT OnStart();
        [id(0x00000003), helpstring("method OnStop")]
        HRESULT OnStop();
        [id(0x00000004), helpstring("method OnExit")]
        HRESULT OnExit();
};

我附上 CANoe.tlb:http ://www.sendspace.com/file/j2zloj

谢谢你的关注达米安

4

2 回答 2

1
  1. 您正在初始化STA并且正在做while(1);,但是请注意,您应该在线程上实现消息泵(提示:快速检查这是否是显示消息框而不是无限循环的原因)
  2. 为什么SINK_ENTRY_INFO而不是SINK_ENTRY任何教程建议的那样?
  3. 您是否有机会查看事件处理程序是否已执行,并在pMeasure->那里调用;您是否检查它是否在此调用中冻结,或者它返回失败结果(或在错误的线程上调用事件处理程序)。
于 2011-12-03T11:35:16.180 回答
0

由于控制台应用程序没有窗口(处理 STA 使用的事件队列),因此您必须调用

CoInitializeEx(NULL,COINIT_MULTITHREADED); 

使用 MTA 而不是 STA

或实现消息泵

MSG msg;
while(GetMessage(&msg,0,0,0))
  DispatchMessage(&msg);  

我还必须将以下代码添加到 stdafx.h 以防止 ATL 类崩溃:

class CDummyModule : public CAtlExeModuleT<CDummyModule> {};
CDummyModule _Module;
于 2017-09-14T08:05:59.057 回答