Friday, March 5, 2010

VOLE breakthrough: Type Tunneling for COM Automation

VOLE is a library for driving COM Automation servers from C++ in a robust and highly-expressive form, with natural syntax, as in:

vole::object search = vole::object::create("recls.COM.FileSearch");
collection   files  = search.invoke_method<collection>(L"Search", rootDir_, pattern_, flags);
{ for(collection::iterator i = files.begin(); i != files.end(); ++i)
{
 using std::string;
 string path = (*i).get_property<string>(L"Path");
 string drive = (*i).get_property<string>(L"Drive");
 string directory = (*i).get_property<string>(L"Directory");
 string dirPath = (*i).get_property<string>(L"DirectoryPath");
 string srchRelPath = (*i).get_property<string>(L"SearchRelativePath");
 string uncDrive = (*i).get_property<string>(L"UNCDrive");
 string file = (*i).get_property<string>(L"File");
 string shortFile = (*i).get_property<string>(L"ShortFile");
 string fileName = (*i).get_property<string>(L"FileName");
 string fileExt= (*i).get_property<string>(L"FileExt");

 long size = (*i).get_property<long>(L"Size");


 bool isReadOnly = (*i).get_property<bool>(L"IsReadOnly");
 bool isDirectory = (*i).get_property<bool>(L"IsDirectory");
 bool isLink = (*i).get_property<bool>(L"IsLink");
 bool isUNC = (*i).get_property<bool>(L"IsUNC");

 SYSTEMTIME crTime = (*i).get_property<SYSTEMTIME>(L"CreationTime");
 SYSTEMTIME modTime = (*i).get_property<SYSTEMTIME>(L"ModificationTime");
 SYSTEMTIME lastAccTime = (*i).get_property<SYSTEMTIME>(L"LastAccessTime");
 SYSTEMTIME lastStChgTime = (*i).get_property<SYSTEMTIME>(L"LastStatusChangeTime");

 collection dirParts = (*i).get_property<collection>(L"DirectoryParts");
}}


As you can see, there's a good amount of flexibility in the return types available, and these can be extended by the user (via return type traits).

Up to (and including) version 0.6 of VOLE, this flexibility was only available for return types; argument types were restricted to those types compatible with the conversion constructors of comstl::variant:
  • bool
  • int8_t
  • uint8_t
  • int16_t
  • uint16_t
  • int32t_t
  • uint32_t
  • int64_t
  • uint64_t
  • float
  • double
  • CY
  • DECIMAL
  • LPUNKNOWN
  • LPDISPATCH
  • char const*
  • wchar_t const*
  • VARIANT
As an example of the Type Tunnel pattern,VOLE has always been going to appear in Breaking Up The Monolith. However, for a long time I've been pondering the presentation, in particular thinking of various options to get around the limitations of the particular Type Tunnel variant - interface mechanism: N-ary Function Templates + tunnel mechanism: Conversion Constructors - used in VOLE.

I've had various ideas, all with unpleasant aspects, of how to get around this and add more flexibility over the months and years during the (glacial) progression of Monolith. But to not much avail.

At the moment I'm trying again to put some momentum back into Monolith, and am almost at a point where the Preface+Prologue are complete, and I can make a formal proposal. A couple of days ago I was reworking the chapter on VOLE, with the hope of using it as one of the sample chapters, and had something of a revelation on the arguments flexibility issue. Very pleasingly, I've found a clean and extensible way to provide all the flexibility required. You'll be able to read about it in the book, hopefully before the end of this year!

Matt