Ticket #82 (closed defect: fixed)
IUnknown is not unique
Reported by: | jasper | Owned by: | jasper |
---|---|---|---|
Priority: | major | Milestone: | Maintenance of Phase II |
Component: | COMBIA | Version: | 1.2.0.8 |
Keywords: | Cc: |
Description
In a scenario where a COBIA object is exposed to COM via COBIA, a wrapper is placed around the object.
If a COBIA object is passed as an argument to COM, through a COMBIA call, this object is also wrapped by a COM object.
If the object that is passed as an argument was already wrapped, this leads to a second COM wrapper being created in case the object is passed as argument as well. This happens for example in ICapeFlowsheetMonitoring::RegisterForEvents?. In this situation, there are two COM objects created for the same COBIA object, and they are therefore observed from the COM side as two different objects. The first argument to RegisterForEvents? of course is means exactly to identify the object (which can be done by QI for IUnknown, as COM rules stipulate that QI for IUnknown on the same object must always return the same pointer).
Change History
comment:2 Changed 3 years ago by jasper
One of the fixed caused a crash - a new operator== on CapeInterface? failed to check for a null pointer. Fixed in revision 228
Also in the custom data interface specification, the data source is passed as argument, and similar scenarios occur.
It is assumed that if you QI for ICapeInterface on a COBIA object, the interface that is returned is unique, just as in COM. All current COBIA object implementations that are based of CapeOpenObject? fulfill this.
An operator== is added to CapeInterface? to check equality against another CapeInterface? or ICapeInterface, as assigning objects to CapeInterface? does not actually do a QI - it does a cast (all CAPE-OPEN interfaces can be cast to ICapeInterface). The operator== does a QI for ICapeInterface on both objects and compares the resulting pointers.
The solution to the multiple COM wrapper creation is to keep a table of COM wrappers that are currently alive, index by unique ICapeInterface pointer. Any COM wrapper created is added to the table, any COM object deleted is removed from the table. If a COM pointer is requested, the table is checked. All of this is shielded by a mutex specific to this table.
A similar construct is created for the opposite direction - wrapped COM objects now return the same wrapper object to COBIA even if passed by argument, and therefore result a unique mapping to ICapeInterface*.