Once you have an IDL file and a DEF file, you're ready to compile the DLL. However, you need to know the names of the MIDL-generated source files before you can write a make file to build them all. So you need the appropriate MIDL command in the make file as well. For both IANIMAL.DLL and IKOALA.DLL, I've used the following command line for MIDL:
midl /ms_ext /app_config /c_ext <name>.idl
where /ms_ext and /c_ext enable Microsoft extensions to IDL (necessary with OLE interfaces) and /app_config allows certain attributes to appear in the IDL file instead of having to be present in another attribute configuration file, or ACF. This is something that you might want to try if you have a lot of interfaces to define.
With this simple command line, MIDL generates the following files by default, assuming that <name> identifies the name of the IDL file, as in the command line above:
<name>_p.c | Source code for the interface proxy and interface stubs |
<name>_i.c | Interface information, such as the structure containing the IID |
<name>.h | The header file that defines the interface for both C and C++ compilers |
dlldata.c | An auxiliary file that contains added information about the DLL |
If you run MIDL on IANIMAL.IDL, you'll end up with IANIMAL_P.C, IANIMAL_I.C, IANIMAL.H, and DLLDATA.C (assuming your operating system supports long filenames). With IKOALA.IDL, you'll have IKOALA_P.C, IKOALA_I.C, IKOALA.H, and DLLDATA.C. MIDL does have a number of command-line options to suppress generation of the proxy or stub side of the code, to suppress generation of header and auxiliary files, and to rename each of these output files. Run MIDL /? or check the MIDL documentation for more information about these options.
Now that you know which files MIDL will generate, you can write a make file to compile these files as you would any other standard C code. You'll probably want to place the MIDL command underneath a dependency on the IDL file, as follows:
ianimal.h ianimal_p.c ianimal_i.c dlldata.c: ianimal.idl
midl /ms_ext /app_config /c_ext ianimal.idl
Both the IANIMAL and IKOALA samples also include the file LIBMAIN.CPP with a custom DLL entry point. This is just to work with this book's make file system and isn't included for any other reason.
If you take a look at the MIDL-generated code, you'll see a lot of calls to Ndr (Network Data Representation) functions in the _p suffix file that the MIDL-generated proxy and stub use to stuff information into the RPC Channel. In addition, the _i suffix file will contain the interface's ID, defined with a structure instead of a macro such as DEFINE_GUID:
typedef struct _IID
{
unsigned long x;
unsigned short s1;
unsigned short s2;
unsigned char c[8];
} IID;
const IID IID_IAnimal =
{{0x0002114a,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
As far as the DLL itself is concerned, there is no reason to store this IID anywhere else. However, clients and servers that are going to implement this interface will need a definition of the IID elsewhere, and for this reason you'll find IID_IAnimal and IID_IKoala listed in INC\BOOKGUID.H. Both EKoala4 and ObjectUser3 include these interfaces. In that same directory, you'll also find copies of MIDL-generated IANIMAL.H and IKOALA.H, which the client and server samples need as well, but they don't care who wrote the header file; nor do they care that these are custom interfaces. From a compiler's point of view, a custom interface header contains the same material as the OLE headers themselves, all interfaces being equal.