2006-02-06

#import - undocumented attribute "no_function_mapping"

I've been working with a rather complex library of 3rd party COM components. One type-library is imported and there are a total of about 3,000 methods. As a result of what I presume to be the 3rd party not adhering to one of "The Rules of COM 101" ("published interfaces are immutable"), I'm kind of in a situation where I need to modify the code generated by the #import (the .tli file, at least).

I #imported the type-library with about 10 attributes to generate the .tlh and .tli files. Then I commented out the #import directive and just #included the .tlh, which in turn #includes the tli. In my case, I needed to modify the .tli so that instead of using the hard-wired DISPIDs that the compiler brought in with the #import, IDispatch::GetIDsOfNames is called to determine the DISPID at runtime. Of course, doing this more than once per program execution isn't efficient, so I wound up creating a local static DISPID variable to hold onto the value, and then a local static bool initialized to false to be the flag that indicates if the DISPID needs to be determined or not. To be thread safe, I entered a critical section prior to testing the bool, and leave the critical section immediately after determining that I've got the DISPID (either in this run, or in a previous one).

One attribute that came in handy in the #import is an undocumented one, "no_function_mapping". This attribute is mentioned in the MS KB article "Description of the no_function_mapping compiler directive and the implementation_key compiler directive in Visual C++ .NET or in Visual C++ 2005". Basically, the "no_function_mapping" attribute is used to disable the "implementation_key" compiler directive, which is used when a type-library has more than 1000 methods. In my case, I didn't need the "implementation_key" (in fact, it kind of cluttered the code) but apparently in other cases it actually causes compiler errors (documented in the KB article).

I don't usually advocate changing compiler-generated code but in this case I made an exception as I plan on thoroughly documenting what I did as well as WHY I did it, and how the idea can be carried forward should additional or newer methods in the 3rd party library be required.

No comments: