6

I am new to COM, and I looked around on the internet to find how to create a COM class in C++ (to be used by C#). I've seen that in the .idl file, I must put something like this:

[
object,
uuid(a93164ee-e6d4-44be-aa27-f00ce6972719),
helpstring("interface ITopologyQuery")
]

interface ITopologyQuery : IUnknown
{
  HRESULT LoadFile(BSTR completeFileName);

  HRESULT SetParameters(int above, int percentage);
}

[
  uuid(a958f2af-8b55-43c4-9fc3-c39d83fc1376)
]
library TopologyQueryLib
{
  [
    uuid(cc814992-31ec-4a1f-a41e-111ade27bdfe),
    helpstring("TopologyQuery class")
  ]
  coclass CTopologyQuery
  {
    [default] interface ITopologyQuery;
  };
}

Now my question is, where do you define the CTopologyQuery class? If I define it as a regular c++ class in another file, will the compiler link my class correctly with the interface? The c++ class code looks like this (it is implemented in a .cpp file):

class CTopologyQuery : public ITopologyQuery
{
  public:

    __stdcall CTopologyQuery();

    //IUnknown interface 
    HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj);
    ULONG   __stdcall AddRef();
    ULONG   __stdcall Release();

    //ITopologyQuery interface
    HRESULT __stdcall LoadTopologyFile(BSTR completeFileName);
    HRESULT __stdcall SetParameters(int above, int percentage);

  private:
};

For now it compiles either if I put the library section in the .idl file or if I don't. I am a little lost as what is the good thing to do here? I understand that the coclass definition is supposed to give a default implementation to the interface, but for me it looks like an empty class with no methods...

Carl
  • 1,224
  • 2
  • 19
  • 35
  • 1
    Hav you read [Exposing COM Components to the .NET Framework (MSDN)](http://msdn.microsoft.com/en-us/library/z6tx9dw3.aspx). This helped a lot when I was trying to understand .Net / COM interop. – Justin Jun 28 '11 at 16:16
  • Are you using ATL? MFC? Or are you doing this all manually? – bdonlan Jun 28 '11 at 16:24
  • 1
    @bdonlan: I am using MFC, and I would like to use ATL but the wizard doesn't work for me (for an obscure reason when it starts it clears my resource additional include directories and then gives me an RC1015 error). So I am trying to do it manually (and at the same time I try to understand how COM works) – Carl Jun 28 '11 at 16:36
  • Okay. Is this an EXE or a DLL? – bdonlan Jun 28 '11 at 16:40
  • Also, in the case of a DLL, is this an in-process or out-of-process server? – bdonlan Jun 28 '11 at 16:43
  • @bdonlan: It is an EXE. I know it is not clean but because of a big legacy bunch of code I want to have an MFC application with a hidden GUI that exposes COM objects. – Carl Jun 28 '11 at 16:51

1 Answers1

6

The IDL (Interface Definition Language) part defines the binary interface in a language-independent way that just looks a lot like C++.

It's generally used to build a binary type library, which is a DLL with info about your COM class. You can use Microsoft's COM/OLE Viewer to browse existing type libraries.

For C++ consumption of your non-IDispatch COM class you don't need that info about your class, since all that the C++ compiler needs to know (as minimum) is in your C++ header file.

But the IDL description and type library generated from that helps to generate the glue code for using your COM class from C# and other languages. As I recall it can also help to generate the Windows registry keys and values needed to use your COM class via CoCreateInstance and friends. So it's a bit of infra-structure machinery, so to speak, essentially supporting a language-independent view and usage of your COM class.

Cheers & hth.,

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • I still don't see how the compiler and the user of the COM interface (ITopologyQuery in this case) know that an instance of CTopologyQuery must be created. And is the "library TopologyQueryLib{...}" block necessary in the .idl file or is it useless? – Carl Jun 28 '11 at 16:40
  • 2
    @Carl: there is no magic, even in COM. The usual way to instantiate a COM object is to call CoCreateInstance, giving it an 128-bit CLSID (which is an UUID) of a class, *and* an 128-bit IID (which is an UUID) of an interface, which the class must provide. It looks up that CLSID in the registry, which gives it a server, DLL or EXE. It then asks that server for an instance. It asks the instance for the interface. I'm a bit vague on how that instantiation works for an EXE server, which is your case. However, for a DLL it's a simple object factory provided by the DLL (well known function). Cheers, – Cheers and hth. - Alf Jun 28 '11 at 16:58
  • @Carl (continued) ... in other words, a user of the COM interface can acquire a provider of that interface by creating an instance of the class that you have said in your IDL implements the interface. Many classes can implement an interface (e.g., all implement IUknown). So that's the purpose of the class definition in the IDL: it serves to inform users that there is at least that class that implements the interface. – Cheers and hth. - Alf Jun 28 '11 at 17:04
  • Alright this clarifies some things thanks. I'll do some testing to help me understand better how things work. – Carl Jun 28 '11 at 17:38