Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 449
  • Last Modified:

URGENT, I need an answer to this COM question

I have created a simple object using the ATL. Within this object I have two contained or "delegated" objects, Obj1 and Obj2.

These "inner" objects need to communicate with one another. Now here is the problem, within a method of Obj1 I perform the following;



     CComQIPtr<IObj2, &IID_IObj2> pobj2 (GetControllingUnknown());


The above code fails because GetControllingUnknown() returns Obj1's OWN IUnknown pointer.

So I tried the following


CComQIPtr<IObj2, &IID_IObj2> pobj2 (m_pOuterUnknown);


This code asserts because m_pOuterUnknown is actually the reference count of Obj1 (if it's not an aggregate thats what it contains)

Is it not possible to query for another interface in contained objects? I cannot determine how to get the "outer" objects IUnknown.

0
johndixson
Asked:
johndixson
  • 6
  • 2
  • 2
  • +2
1 Solution
 
BeyondWuCommented:
>>>These "inner" objects need to communicate with one another.

Why the two inner objects need to communicate? I think each inner objects is invisible for each other. If you want to exchange some information you can through the outer object, because only the outer object know there are two inner object, but the inner object should have some interfaces that let you exchange info inherent.

So, I think you can add some global data or data member in your own CMYComModule _Module; to exchange info.
Or you can provide some interfaces or functions to let the user call it and exchange info between two inner object, because only the outer object know the detail of inner object.

Hope this can help you!
0
 
snoeglerCommented:
You speak of "contained objects", i.e. not aggregates? GetControllingUnknown() works only in aggregated objects, so you can't use it in this context.

You can, though, add another method to each of the contained interfaces (for example, "SetContainer()") and call this method upon instantiation of the contained objects. I'd not suggest using a global member (or even CComModule-Member), because in case of an non-singleton object you'll run into big trouble.
0
 
elcapitanCommented:
try this:

//create CComPtr object
CComPtr<IObj2> pobj2;

//create instance
HRESULT hr=pobj2.CoCreateInstance(__uuidof(Obj2));hr=

//call methods of your object
pobj2->whatever(/*params*/);

--EC--
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
elcapitanCommented:
Sorry, I made a mistake. now it's fine:

//create CComPtr object
CComPtr<IObj2> pobj2;

//create instance
HRESULT hr=pobj2.CoCreateInstance(__uuidof(Obj2));

//call methods of your object
hr=pobj2->whatever(/*params*/);

--EC--
0
 
johndixsonAuthor Commented:
--EC--

This creates a new instance of the component, I need to use the "outer" objects instance of the component.
0
 
ambienceCommented:
>> CComQIPtr<IObj2, &IID_IObj2> pobj2 (GetControllingUnknown());
The above code fails because GetControllingUnknown() returns Obj1's OWN IUnknown pointer.
So I tried the following
CComQIPtr<IObj2, &IID_IObj2> pobj2 (m_pOuterUnknown);

This all suggests that you are not creating the objects as aggregates also pointed out by snoegler.

Now here is the conceptual fight, IUnknown of the contaier is only logical to an aggregate and for an object that is not created as aggregate or which doesnot support aggregation pointer to parent is meaning less.


can post the code where you are creating the contained objects ?, do the objects support aggrgation ?

CComAggObject <CObj1> *pObj = CComAggObject <CObj1>::CreateInstance(....);

0
 
johndixsonAuthor Commented:
Ambience,

Here is the where the contained objects are being created. The objects formally know as OBj1 (Now cambackground) and Obj2 (now camteperature);

[ccode]
     HRESULT FinalConstruct()
     {
          // create contained components
          HRESULT     hr;
               hr = CoCreateInstance(CLSID_CamBackground, 0,
                    CLSCTX_INPROC_SERVER, IID_ICamBackground, (void**)&m_pCamBackground);


          // set temperature
          if (SUCCEEDED(hr))
               hr = CoCreateInstance(CLSID_CamSetTemp, 0, CLSCTX_INPROC_SERVER,
                    IID_ICamSetTemp, (void**)&m_pCamSetTemp);
return hr;
}

private:
IUnknown* m_pCamBackground;
IUnknown* m_pCamSetTemp;
[/ccode]

The objects do infact support aggregration, but they cannot be aggregrates.

It is my understanding that delegation is a constrained form of containment where an interface on the outer object is implemented by calls to the methods of the identical interface on the inner object. The delegated call to the method on the inner object may be preceeded and followed by other code implemented by the outer object.

This is in fact exactly what I need to perform. The inner objects are used to verify and configure hardware settings but the actual call to apply these settings is specific to the hardware in use.

Take for instance the background object above. It has a method called NeedNewDark(). This method needs to ask the temperature object what the current temperature of the CCD camera is. If the camera temperature has changed by more the a specified amount that is configured in the background object a new "background" acquisition needs to be performed.
0
 
johndixsonAuthor Commented:
Ambience,

Here is the where the contained objects are being created. The objects formally know as OBj1 (Now cambackground) and Obj2 (now camteperature);


...
...
     HRESULT FinalConstruct()
     {
          // create contained components
          HRESULT     hr;
               hr = CoCreateInstance(CLSID_CamBackground, 0,
                    CLSCTX_INPROC_SERVER, IID_ICamBackground, (void**)&m_pCamBackground);


          // set temperature
          if (SUCCEEDED(hr))
               hr = CoCreateInstance(CLSID_CamSetTemp, 0, CLSCTX_INPROC_SERVER,
                    IID_ICamSetTemp, (void**)&m_pCamSetTemp);
return hr;
}

private:
IUnknown* m_pCamBackground;
IUnknown* m_pCamSetTemp;

...
...

The objects do infact support aggregration, but they cannot be aggregrates.

It is my understanding that delegation is a constrained form of containment where an interface on the outer object is implemented by calls to the methods of the identical interface on the inner object. The delegated call to the method on the inner object may be preceeded and followed by other code implemented by the outer object.

This is in fact exactly what I need to perform. The inner objects are used to verify and configure hardware settings but the actual call to apply these settings is specific to the hardware in use.

Take for instance the background object above. It has a method called NeedNewDark(). This method needs to ask the temperature object what the current temperature of the CCD camera is. If the camera temperature has changed by more the a specified amount that is configured in the background object a new "background" acquisition needs to be performed.
0
 
johndixsonAuthor Commented:
Ambience,

Here is the where the contained objects are being created. The objects formally know as OBj1 (Now cambackground) and Obj2 (now camteperature);


...
...
     HRESULT FinalConstruct()
     {
          // create contained components
          HRESULT     hr;
               hr = CoCreateInstance(CLSID_CamBackground, 0,
                    CLSCTX_INPROC_SERVER, IID_ICamBackground, (void**)&m_pCamBackground);


          // set temperature
          if (SUCCEEDED(hr))
               hr = CoCreateInstance(CLSID_CamSetTemp, 0, CLSCTX_INPROC_SERVER,
                    IID_ICamSetTemp, (void**)&m_pCamSetTemp);
return hr;
}

private:
IUnknown* m_pCamBackground;
IUnknown* m_pCamSetTemp;

...
...

The objects do infact support aggregration, but they cannot be aggregrates.

It is my understanding that delegation is a constrained form of containment where an interface on the outer object is implemented by calls to the methods of the identical interface on the inner object. The delegated call to the method on the inner object may be preceeded and followed by other code implemented by the outer object.

This is in fact exactly what I need to perform. The inner objects are used to verify and configure hardware settings but the actual call to apply these settings is specific to the hardware in use.

Take for instance the background object above. It has a method called NeedNewDark(). This method needs to ask the temperature object what the current temperature of the CCD camera is. If the camera temperature has changed by more the a specified amount that is configured in the background object a new "background" acquisition needs to be performed.
0
 
johndixsonAuthor Commented:
Sorry about the triple post, I am used to posting and having a "preview".
0
 
ambienceCommented:
>> The objects do infact support aggregration, but they cannot be aggregrates

Why not ?

>> CoCreateInstance(CLSID_CamBackground, 0,
                   CLSCTX_INPROC_SERVER, IID_ICamBackground, (void**)&m_pCamBackground);

The second parameter is 0 so no aggregation therefore no way to Query for outer unknown, as there is none (from contained objects point of view).

You need to aggregate them, for e.g. if all the objects are in the same project you may do something like

CComAggObject< CCamBackground >* pObj1;
pObj1 = CComAggObject< CCamBackground >::CreateInstance( outerUnknown ,..);

If you are not willing to aggregate them, then the one way is as mentioned by snoegler to add a method like SetContainer or SetOuterUnknown.

Or perhaps you can add a method like SetTemparatureObj() and pass the IUnknown of temparature object, this lets you call the object directly without involving the container.

Third way depends on whether your CamBackground and CamTemparature objects can be singletons or not, if they are singletons then there is no need for any intermediate unknown, whenever you need a CamBackground just CreataInstance one, since it is a singleton you'll always have only one instance running and Creating will only return a pointer to existing instance.

for that you can add DECLARE_CLASSFACTORY_SINGLETON(..) to your objects.

Hope this helps
0
 
johndixsonAuthor Commented:
Ambience,

I am glad that you pointed out the DECLARE_CLASSFACTORY_SINGLETON(..) template to my because in fact there can only be one instance of this control running at any one time.

I do beleive this will solve my problem and I'll let you know at a later date.

Thanks,

John
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 6
  • 2
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now