开发者

C++ Exposed property for COM in idl is showing as lower case "all of a sudden"

I have this old C++ COM component. I took the latest code base, built it and found that one of the properties has become lower case. For example, in the p开发者_如何学Pythonre-compiled dll i have a property "Type", but when building from source it's called "type". The idl shows that the property is called "Type". So what could possibly be happening here?


COM is case-insensitive, so there is only one entry in the library's symbol table for the symbol "type". The version which is put into the symbol table is the first one that the compiler encounters.

Microsoft's advice on the matter is simply:

Make sure that the same name is not already present in the IDL file when introducing a new identifier.

You should stick to either Type or type in the IDL, for consistent results.


You discovered a quirk in the OS stock implementation of ICreateTypeLib, used by practically all tool chains on Windows that can create a type library. It uses a rather crude way to deal with possible problems caused by languages that are not case-sensitive, VB/A being a prominent example.

At issue is the definition of an identifier with one casing, being referenced elsewhere in the type library with another casing. Not a problem at all in, say, VB, big problem when the client programmer uses a case-sensitive language like C# or C++.

The "fix" it uses is to force the casing to be consistent everywhere in the library. Unfortunately it is not very sophisticated about it. Best example is a method declaration earlier in the type library that takes an argument named type. Any identifier named Type in the rest of the type library will now get case-converted to type.

Repairing this problem is easy enough, just change the name of the identifier so it no longer matches. You'll have to find it, not so easy, best to use Oleview.exe, File > View Typelib command. Copy/paste the decompiled IDL into a text editor and use its Search command.


I had the same problem almost 10 years after this question was asked and I would like to share my solution (thanks for the help in understanding the problem).

First I would like to say that I had several names whose casing was changed by tlbimp and changing all the instances of these names to my expected casing in the IDL fixed all but one. I'm assuming that that name (Text) came from a different IDL I imported. I was also not happy with the solution of changing the names of parameters and the like since in the future someone else may change them.

The solution I found was to introduce a dummy interface with the casing I wanted. I did this before all other imports and then referenced it in the library section of the IDL. Note that both these details are required. If you don't put it in the library section it's ignored and if I defined it at the beginning of the library section after the imports it's too late.

import "oaidl.idl";
import "ocidl.idl";

[
    uuid(4EA92D5A-BF84-46C4-AA38-0F7DEADC69B),
    helpstring("Ensure that names used in interop have correct casing")
]
interface IAmHack : IUnknown
{
    HRESULT Space();
    HRESULT The();
    HRESULT Final();
    HRESULT Frontier();
};

// ...

library MyLib
{
    interface IAmHack;

    importlib("stdole2.tlb");
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜