I strongly recommend you to create an IDL file to design your COM interfaces.
Given your example in your answer, a rather minimal IDL file could be like this:
import "oaidl.idl";
[object,
uuid(1f6efffc-0ac7-3221-8175-5272a09cea82),
dual,
oleautomation]
interface IStreamFrame : IDispatch {
[propget]
HRESULT Width([out, retval] long *pWidth);
[propget]
HRESULT Height([out, retval] long *pHeight);
[propget]
HRESULT Buffer([out, retval] SAFEARRAY(byte) *pBuffer);
};
[uuid(1f6efffc-0ac7-3221-8175-5272a09cea83)]
library ContosoStreamFrame {
importlib("stdole32.tlb");
interface IStreamFrame;
};
You then use midl.exe
to generate a .h with C/C++ interfaces, a _i.c for the CLSID and IID constants for C/C++ linking, a dlldata.c for RPC registering, a _p.c with proxy and stub marshalling stuff and a .tlb which is in general terms the parsed representation of the .idl file. This is all better described in the documentation.
EDIT: There seems to be no way to avoid the C/C++ file generation.
EDIT2: I just found a workaround, use nul
as the output file for what you don't want. For instance, the following command only generates file.tlb
:
midl.exe /header nul /iid nul /proxy nul /dlldata nul file.idl
Note: if your IStreamFrame
interface is not meant to be used across processes, add the local
attribute to the interface.
In C/C++, you can use the specific files that are generated, or #import
the TLB file. In .NET, you can run tlbimp.exe
on the TLB file, which generates a .NET assembly.
You can also use tlbexp.exe
if your project is .NET centric. However, that'll require you to know the .NET COM annotations and what they mean in terms of IDL, so I'm not sure if there's any gain on saving one extra source-file in another language at the expense of lots of decoration noise in your interface and class definitions. It's perhaps a good option if you want to have full control of the classes and interfaces at the source level and you want to make it as easy as possible (read, optimized for usability and maybe speed) on .NET code.
Finally, you can automate all of this in Visual Studio by creating a project. If you use the IDL approach, add a custom build step that invokes midl.exe
and tlbimp.exe
and make the dependant projects depend on this project for a correct build order. If you use the .NET approach, add a custom build step that invokes tlbexp.exe
and make the dependant C/C++ projects depend on this project.
EDIT: If you don't need the generated C/C++ files from midl.exe
, you may add del
commands to your custom build step for the specific output files.
EDIT2: Or use the nul
workaround described above.
A common approach used when the type library already exists is to use Visual Studio to import it into .NET. But this way, you'll have to remember to regenerate the TLB and import it again if you update your IDL file.