I am creating an in-process COM server using ATL. Among the types that this COM server will expose is an enum. The values of this enum need to be defined using values from another COM server that this COM server depends on. I've tried pretty much everything I can think of to get this to work with no real success at all.
Here is the IDL for the COM server dependency.
Type1Lib.idl
import "oaidl.idl";
import "ocidl.idl";
[
uuid(B777544C-77D9-4417-8302-4EAC8272DEDC),
version(1.0),
]
library Type1Lib
{
// required system import.
importlib("stdole2.tlb");
// A simple enum to be used by another COM server.
typedef
[
uuid(EF82F7A5-3A55-44B9-AD06-201A6D0A6021)
]
enum Enum1
{
One,
Two,
Three,
Four,
Five
} Enum1;
};
Here is the IDL for the COM server dependent that is trying to use Enum1 (including some of the approaches I've tried).
Type2Lib.idl
// Required system imports.
import "oaidl.idl";
import "ocidl.idl";
// (2) FAIL Enables use of Type1Lib enums in this idl file but only as long as usage
// of those types is totally unqualified. The problem with that is that when a tlh file
// is generated from the type library this idl file creates, that tlh file is malformed
// because the unqualified enum references do not resolve to anything.
import "Type1Lib.idl";
// FAIL Neither of these statements even compiles, Emits error:
// "Native Compiler support only available in C++ compiler".
// The tlh is C++ and apparently cannot be parsed by MIDL.
//import "type1lib.tlh";
//#include "type1lib.tlh"
[
uuid(D40AC182-8744-42D1-B194-602AEDDC6E7C),
version(1.0),
]
library Type2Lib
{
// Required system import.
importlib("stdole2.tlb");
// Import Type1Lib without redeclaring the types it contains.
// (1) FAIL Enables usage of the enum type in Type1Lib, but not the enum values,
// so that's utterly useless.
// importlib("Type1Lib.dll");
typedef
[
uuid("0B8D400A-6A8F-44B3-986D-9E099830BB6D")
]
enum Enum2
{
A = 0x80000000 + One, // One references an enum value from Type1Lib.
B,
C,
D,
E
} Enum2;
[
object,
uuid(F5BA0CB0-B7C7-4483-A3D9-D4B9E39E6269),
dual,
nonextensible,
pointer_default(unique)
]
interface IType2 : IDispatch
{
[id(1)] HRESULT Method1([out,retval] LONG* retVal);
// Partial success. Can reference typedef'ed enum using importlib. Cannot however access the enum values.
[id(2)] HRESULT Method2([in] enum Enum1 arg1);
};
[
uuid(6179272F-4B34-4EF0-926B-296D3AA73DB7)
]
dispinterface _IType2Events
{
properties:
methods:
};
[
uuid(75CE545A-D2DA-4EC9-80CF-37531516DFC1)
]
coclass Type2
{
[default] interface IType2;
[default, source] dispinterface _IType2Events;
};
};
So using importlib on the typelibrary (embedded in the dll) doesn't work because it doesn't permit access to the values of Enum1.
import'ing Type1Lib.idl doesn't quite work because although the enum values are available they can only be used in unqualified form, so although Type2Lib.idl now compiles, when Type2Lib_i.h is included in dllmain.cpp the enum values do not resolve to anything. Another problem is that the import "Type1Lib.idl" statement causes the addition of an "#include "Type1Lib.h"" line in Type2Lib_i.h, the file Type1lib.h does not exist and there is no reason why it should exist.
There are workarounds for both these problems but they don't really result in a workable solution overall.
Importing Type1Lib with no_namespace in stdafx.h will resolve the issue of the unqualified enums not resolving, but now you are opening yourself up to the possibility of typename clashes that you are unable to work around because now you can't use namespaces.
Prior to importing Type1Lib in stdafx.h you can use a #pragma include_alias to redirect the #include "Type1Lib.h" from a header that doesn't exist to one that does, e.g.
#pragma include_alias("Type1Lib.h", "windows.h")
#import <Type1Lib.dll> no_namespace
Now everything builds. The problem is you now have several nasty and fragile workarounds in play just waiting to screw everything up, and there is still one other glaring issue that I haven't mentioned yet which is this. If you reference your COM dependency via 'importlib' then you get just that, a reference to your dependency, your IDL file can use the types in the referenced typelibrary but you won't be redefining anything. If however you import the idl file using 'import' then what you basically have is a version of 'include' tweaked for use in IDL files. The issue with this is that using 'import' will result in creating duplicates of the types in your dependency IDL file in your dependent IDL file, which you most definitely do not want.
So I'm at a complete loss. What I want to do appears to be pretty straightforward yet despite trying everything I can think of I'm left seeing nothing but wrongness. I desperately need some COM guru to put me on a useful path here.