views:

93

answers:

3

Hello, guys! Very important question:

Please, look at my project (300Kb). I can`t use MFC/ATL, pure C++ only.

I have COM library (niapi.dll), but no sources/headers available, dll only.

There is class for connecting to server (NiApi::SrvrSession), class has login event handler (NiApi::SrvrSession::OnLogin).

I used

#import "NiApi.dll"

to generate wrappers/information,

then

ISrvrSessionPtr session(L"NiApi.SrvrSession");

to create object, then trying

session->put_OnLogin();

to assign events, but there is no one put_On or such member.

niapi.tlh have _ISrvrSessionEvents struct inside, but it have no relations with SrvrSession.

I need to use events from NiApi::SrvrSession for handling connection status.

Please help or my boss kill me! (sorry for broken english, I read better than speak;)

A: 

The put_ prefix is the default prefix for the raw interface (customizable via the raw_property_prefixes attribute). Since you are not using the raw interface, use session->OnLogin=... instead.

For event handling see ADO Events Model Example (VC++)

Sheng Jiang 蒋晟
Thanks. But no session->OnLogin in class, no membber that contains 'Login' at all.
Artem
+2  A: 

COM events are handled via connection points. You need to write your own COM object that implements whichever event interface you are interested in. Then you need to connect it to the COM object that fires the events. First you QI the COM object for its IConnectionPointContainer, then find the corresponding connection point of the GUID of the event interface. The you call its Advise method to connect it to your event sink.

class CSrvrSessionEvents: public _ISrvrSessionEvents
{
public:
    HRESULT OnLogin(long LoginResult)
    {
        // do something
        return S_OK;
    }
    // implement rest of _ISrvrSessionEvents
};

ISrvrSession* pSrvrSession = ...; // get ISrvrSession from somewhere
_ISrvrSessionEvents* pSrvrSessionEvents = new CSrvrSessionEvents();
IConnectionPointContainer* pCPC = NULL;
pSrvrSession->QueryInterface(IID_IConnectionPointContainer, &pCPC);
IConnectionPoint* pCP = NULL;
pCPC->FindConnectionPoint(__uuidof(_ISrvrSessionEvents), &pCP);
DWORD dwCookie = 0;
pCP->Advise(pSrvrSessionEvents, &dwCookie);
pSrvrSession->Connect(); // I assume this fires some events
pCP->Unadvise(dwCookie);
Luke
I meet COM 4 hours ago and my brain is going to crack :) Luke, I promise, within few days I will become a COM-Guru! But at that moment I need the simpliest way for handling events. We have ISrvrSession and _ISrvrSessionEvents in niapi.tlh, must be the simpliest way to make them work together! (Wrong?)COM DLL is binary, event handling must be already implemented in DLL. (Wrong?)If that 'Sinks' are only way to handle events, please, show me some more specific code, that a bit easy to understand. please, please, please!
Artem
@Artem: Luke pretty much spelled it out for you. Unfortunately COM is not easy to understand, and by implementing connection points directly in C++ without the use of ATL, you are doing something pretty advanced that most COM experts would have to think about. I suggest you start studying books on COM. 4 hours isn't going to get you there. More like 4 weeks.
John Dibling
@Artem: I understand that seeing so much code to do a seemingly simple thing scares you, but sad truth is all the code above is necessary and some importand details are even omitted.
sharptooth
@Luke: +1, but... You completely omitted the moment how the object is to be `Release()` d and also you don't specify how the refcount is initialized in the constructor. If you mean it is set to one - okay, but otherwise calling `AddRef()` immediately after `new` is necessary to prevent accidential deletion and for proper lifetime management.
sharptooth
Luke, you are my hero!
Artem
A: 

What is really necessary, is to carefully read http://www.codeproject.com/kb/com/TEventHandler.aspx.

All explainrd here.

Thanks to all for help!

Artem
It is quite simple, when you understand what are you doing.
Artem