COleSafeArray vs CComSafeArray - c++

I am in a situation where I have a COM object that I need to use in come windows only C++ code. The COM object has functions that accept SAFEARRAYs as arguments to pass arrays of bytes. After looking at the SAFEARRAY API ( http://msdn.microsoft.com/en-us/library/windows/desktop/ms221145(v=vs.85).aspx ) I decided it wasn't what I wanted and that I should find an object oriented wrapper. I tried looking for open source ones and I didn't find any. I found that microsoft has created two objects that seem to encapsulate SAFEARRAY. It looks like the CComSafeArray is exactly what I need, and like the the COleSafeArray might be useful but could exist only for legacy compatibility.
Is COleSafeArray just around for historical compatibility or is there something I am missing?
When should COleSafeArray be used instead of CComSafeArray?
Are there any open source implementations that might be worth looking into?
What are the Pros and Cons of each?

The difference is obvious from class names.
MFC COleSafeArray is designed to support OLE Automation and is actually wrapper for OLE VARIANT struct (which can contain SAFEARRAY). It works generally with array elements as they are of VARIANT type so you need to select & extract appropriate type manually.
ATL CComSafeArray is designed to support SAFEARRAY for generic COM and is actually wrapper for SAFEARRAY struct. It's template class parametrized with array elements type.
In general you shall use CComSafeArray, it's easier and simplier, accessing elements almost same way as for regular arrays/vectors.
COleSafeArray may be preferable sometimes if you work with OLE Automation interfaces that intensively use VARIANT parameters, e.g. automating MS Office, using Visual Basic components etc. For comparision in this case with CComSafeArray you will need to wrap/unwrap it manually to/from VARIANT object.

Related

How to pass a C++ Map into a RTI DDS connext Publisher and receive at RTI Subscriber

I am new to RTI DDS connext. I tried running some C++ examples(Hello_dynamic,Hello_simple) of rti and they where working fine.Then i thought of passing a C++ map as Topic type from publisher to Subscriber.But i guess their is no documentation and example codes are available for doing this. Please help me here ..??
The C++ standard map type can not natively be used as a Topic type. DDS can distribute any type that can be expressed by a defined subset of OMG's IDL (Interface Definition Language) and the map type is not among that.
The two code examples that you are referring to are not your typical situation, because they rely on the built-in string type (Hello_simple) or the proprietary dynamic data API (Hello_dynamic). To get a better idea how you would normally define your own datatypes, check out the Hello_idl example. It shows a user-defined type, defined in IDL, that is translated into a C++ type to be used by your application.
It would be fairly easy to create a Topic type to achieve functionality similar to a C++ map. Suppose your map-items have string keys and long values, then you could use a structure in IDL to express a single item in your map, for example using the following type:
struct mapItem {
unsigned long m_mapId; //#key
string m_key; //#key
long m_value;
};
m-mapId indicates to which map this item belongs. Your map is the collection of all mapItems with the same m_mapId value. The fields m_key and m_value are obviously the key-value pairs.
On the publisher side, your application can write the map elements to DDS one-by-one. Values with the same values for m_mapId and m_key will overwrite each other, resulting in the same behavior as expected for standard maps. On the subscriber side, it is possible to build up the complete map by querying the datareader for all mapItems with the same m_mapId.
Your application code will not be using standard maps when using this approach. In order to achieve that, you will have to create wrapper functions that translate a map(-like) API into the corresponding write and read actions.
In case you are familiar with regular data-base designs, you will notice the similarity to what you would be doing when designing this in a relational data model. Indeed, DDS can be considered a distributed data management infrastructure with a lot of similarities to regular DBMS-es.

How to send list through COM

Can I send a list of objects through COM?
I have my class and there is also a list of this class. And I need to send this through a COM function. Can I do that? If yes, then how? Do I need serialization marshaling?
COM does not pin down any particular collection type, it certainly doesn't have anything standard that models a list. By convention, you can model any collection with an interface. So say you have a collection of Foo objects that each implement IFoo. Then declare an IEnumFoo interface similar to:
interface IEnumFoo : IUnknown
{
HRESULT Next( [in] ULONG celt,
[out, size_is(celt), length_is(*pceltFetched)] IFoo **rgelt,
[in,out,unique] ULONG *pceltFetched );
HRESULT Skip( [in] ULONG celt);
HRESULT Reset();
HRESULT Clone( [out] IEnumFoo **ppenum );
}
And then simply return an interface pointer to an implementation of this interface to allow the client code to enumerate the list. Check the MSDN docs for IEnumVARIANT, a very common enumeration interface type for variants. Which also explains what the methods do.
If one side of the interface will be written in a language with a "simpler" type system, such as VB6 or script, then the SAFEARRAY is the way to go. COM's universal marshaller can take care of it.
If you have C++ on both sides of the interface, and you're happy to define the interface in IDL, and generate custom marshalling code, then IDL includes a "size_is" attribute that can be used. See here for details.
To any reasonable degree, there's no way to do so with std::list. I'm sure there is some maniac who could manage it but from my experience, it's not worth it. If doesn't have to be an std::list and just some linked list, then you'll have to either define a new COM interface and provide it's implementation (which can just be a wrapper around std::list) or find some thirdparty resource that has an adequate implementation for your purposes. If you don't have much experience with implementing COM interfaces, then you'll need to do some good amount of reading.
If it can be an array, then you can make your life a lot simpler by using a SAFEARRAY. And SAFEARRAYs can be easier to use with ATL's CComSafeArray, which is pretty much a wrapper. It tries to help/save you from issues, such as reference counting, when dealing with COM objects. You can then just pass the array between your COM objects. Just going to remind you that you still need to pay attention to who is responsible for de-allocating the memory.

Returning a flexible datatype from a C++ function

I'm developing for a legacy C++ application which uses ODBC for it's data access. Coming from a C# background, I really miss the ADO style of data access.
I'm writing a wrapper (because we can't actually use ADO) to make our data access less painful. This means no char arrays, no manual text blob streaming, and no declaritive column binding.
I'm struggling with how to store / return data values. In C# at least, you can declare an object and cast it to whatever (as long as the type is convertable).
My current C++ solution is to use boost::any to store the data value in a custom DataColumnValue object. This class has conversion and assignment operators to the various types used in our app (more than 10). There's a bit of complexity here because if you store an int in the boost::any and try to boost::any_cast<long> you get a boost::bad_any_cast. Client objects shouldn't have to know how the value is stored internally.
Does anyone have any experience trying to store / return values whose types are only known at runtime? Is there a better / cleaner way?
I used OTL (http://otl.sourceforge.net/) in some one-off projects back in the day for interfacing C++ and some SQL Server databases. It's streams-based, so it can do type conversion for you. I did find the streams paradigm a bit confusing at times, as I had to unstream the values in the query order - I never quite figured out how to pull a named value out of the record stream.
But it worked flawlessly otherwise.
In regards to Boost.Any, I've implemented similar constructs before, copying the COM Variant as a C++ union. With Boost.Variant/Any you might need to add addition template specializations to support the particular datatype conversions you're attempting (long is not an int after all). I don't see any particular downside to your approach except scalability in number of types.

How to create a VB6 collection object with ATL

or a VB6 - compatible - collection object.
We provide hooks into our .net products through a set of API's.
We need to continue to support customers that call our API's from VB6, so we need to continue supporting VB6 collection objects (simple with VBA.Collection in .net).
The problem is supporting some sites that use VBScript to call our API's. VBScript has no concept of a collection object, so to create a collection object to pass to our API we built a VB6 ActiveX DLL that provides a "CreateCollection" method. This method simply creates and passes back a new collection object. Problem solved.
After many years of pruning, porting and re-building, this DLL is the only VB6 code we have. Because of it we still need to install Visual Studio 6 on our Dev & build Machines.
I'm not happy with our reliance on this DLL for several reasons (my personal dislike of VB6 is not one of them). Top of the list is that Microsoft no longer support Visual Studio 6.
My question is, how do I get ATL to create a collection object that implements the same interface as the VB6 collection object.
I've a good handle on C++, but only a loose grasp of ATL - I can create simple objects and implement simple methods, but this is beyond me.
Collections are more or less based on convention. They implement IDispatch and expose some standard methods and properties:
Add() - optional
Remove() - optional
Item()
Count - read-only
_NewEnum - hidden, read-only, returns pointer to enumerator object that implements IEnumVariant
The _NewEnum property is what allows Visual Basic For Each.
In the IDL you use a dual interface and:
DISPID_VALUE for Item()
[propget, id(DISPID_NEWENUM), restricted] HRESULT _NewEnum([out, retval] IUnknown** pVal)
Here are some MSDN entries: Design Considerations for ActiveX Objects
And here is some ATL specific convenience: ATL Collections and Enumerators
Lets target this VBScript snippet
Dim vElem
For Each vElem In MyObject
...
Next
particularly the implementation of MyObject. As a minimum you have to implement a method/propget with DISPID_NEWENUM on the default dispinterface (its dual/dispinterface to talk about DISPIDs). You can name it whatever you want, it doesn't matter. Most collections use NewEnum, and flag it in IDL as hidden. VB6 uses underscore prefix to mark hidden methods so you might see _NewEnum as recommendation but it's kind of a cargo cult ATL does.
You don't need any Count, Item, Add, Remove, Clear or any other method at all (on the default interface). You can supply these as a convenience (particulatly Item accessor and probably Count) but you don't have to, to make the sample code above work.
Next, the retval has to be a separate object (so called enumerator) which implements IEnumVARIANT interface by using a (private) pointer to MyObject. In IDL you can declare retval as IUnknown nothing wrong here. What is most interesting is that you have to implement only the Next method on IEnumVARIANT, you can return E_NOTIMPLEMENTED on the rest if you like or optionally implement them though these are never called by For Each. What makes the implementation even easier is that celt parameter of Next (the number of items requested) is always 1, so For Each requests items always one by one.
What you can use in ATL is CComEnumOnSTL and the like to create a "proxy" enumerator on an STL container, or the array based enumerator ATL provides (and exclude STL).
For a good example of how to implement COM collections that would be used naturally in script programming languages, check out my website
It offers a comprehensive example of how to do that...

What is the typical usage of boost any library?

What are the advantages of using boost.any library ? Could you please give me some real life examples ? Why the same functionality couldn't be achieved by having some generic type in the root of object's hierarchy and creating containers with that base type ?
boost::any will happily store ints and floats, types that clearly have no base classes. A real-life example where you can use it is a virtual machine for a high-level interpreted language. Your "function" objects will need an array of arguments. This can easily be implemented with a std::list<boost::any> behind the scenes.
I consider that Boost.Variant should always be preferred as it's non-intrusive and still calls for very structured programming.
But i guess the main idea behind boost.any is to provide the equivalent of java and c# object types. It's a way of saying "yes we can" ! :-)
We've used it in a property map, (std::map<std::string, boost::any>), to store a lot of things dynamically in a simple, flat dataspace.
Mostly we either stored smart-ptr-to-scriptable-objects or strings, but some entries where other types (floats, vec3f, matrices, and other non-standard objects).
It works pretty well for adding more dynamic capabilities to c++, or wherever you want some type-erasure to just add any type of data to an object.
Why the same functionality couldn't be achieved by having some generic type in the root of object's hierarchy and creating containers with that base type ?
That calls an object hierarchy -- a construct you are injecting in artificially in to the design for solving a peripheral problem. Further, such a construct is easy to get wrong and a wrong implementation can wreak havoc. Boost.Any is a community reviewed safe, well-tested alternative.
Could you please give me some real life examples ?
TinyJSON uses boost.Any.
What are the advantages of using boost.any library ?
I refer the introductory documentation.
We use boost.any as the carrier type for a type-safe tagged variadic container. Here's what that means:
We have a "raft" object, which travels through a set of filters. When a filter wants to add data to the raft, it can do something like this:
raft.addTaggedData<ETag1>(3.0);
raft.addTaggedData<ETag2>("a string")`;
std::string str = raft.getTaggedData<ETag2>();
int a = raft.getTaggedData<ETag1>(); // <-- Compile error
Where ETag1 and ETag2 are members of an enum, and we use a traits template to map tags to types.
The raft class is using a list of pair<ETagType, boost::any> as a backing store. Boost.any saved us the pain of managing raw buffers for various types.