我是COM编程的新手。
我有很大的问题。我正在尝试通过COM Server处理来自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
感谢您的关注 达米安
答案 0 :(得分:1)
STA
并且您正在执行while(1);
,但请注意,您应该在线程上实现消息泵(提示:快速检查是否这是显示的原因)消息框而不是无限循环)SINK_ENTRY_INFO
而不是SINK_ENTRY
,正如任何教程所暗示的那样?pMeasure->
;你检查它是否在此调用中冻结,或者它返回失败结果(或者在错误的线程上调用事件处理程序)。答案 1 :(得分:0)
由于控制台应用程序没有Window(处理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;