Migrating C++ Code from #import to TLIBIMP.EXE

From RAD Studio
Jump to: navigation, search

Go Up to TLIBIMP.EXE


This topic describes issues that you need to resolve when you change from using #import to using TLIBIMP.EXE in order to correctly import a type library. If you attempt to use #import, the C++ compiler emits the warning W8137 Deprecated #import directive encountered. Please use the TLIBIMP utility instead. (C++).

TLIBIMP.EXE and the #import directive generate different GUIDs for a given coclass:

  • With #import: __uuidof(CoClass) returns the GUID of the CoClass.
  • With TLIBIMP: __uuidof(CoClass) returns the GUID of the default interface of the CoClass.

For example, here is the code generated by #import for the type library represented by the following .ridl snippet:

[
  uuid(ECD2547D-5BC5-49C6-A7D1-9D55C0A9F0DF),
  version(1.0)
 
]
library Project14
{
 
  importlib("stdole2.tlb");
 
  coclass CoClass1;
  interface Interface1;
  
  [
    uuid(AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA),
    dual,
    oleautomation
  ]
  interface Interface1: IDispatch
  {
  };
 
  [
    uuid(cccccccc-cccc-cccc-cccc-cccccccccccc)
  ]
  coclass CoClass1
  {
    [default] interface Interface1;
  }; 
};

For CoClass1 from the type library above, #import generates the following declaration (behind the scenes):

struct __declspec(uuid("cccccccc-cccc-cccc-cccc-cccccccccccc"))
CoClass1;

In other words, when you use #import, the GUID associated with the type CoClass1 is indeed the GUID of the CoClass.

TLIBIMP, however, generates the following declaration for CoClass1:

interface DECLSPEC_UUID("{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA}") Interface1;
 
typedef Interface1 CoClass1;

So code that uses __uuidof(CoClass1) with #import does not work when using the binding generated by TLIBIMP.

For example, following code does not work:

#include <stdio.h>
#import "test.tlb"
 
using namespace TestLibrary;
 
int main()
{
  GUID g = __uuidof(CoClass1);
  printf("GUID of CoClass1"
         " = {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
                              g.Data1, g.Data2, g.Data3,
                              g.Data4[0], g.Data4[1], 
                              g.Data4[2], g.Data4[3],
                              g.Data4[4], g.Data4[5], 
                              g.Data4[6], g.Data4[7]);
  return 0;
}

So when switching from #import to a unit generated by TLIBIMP, you must watch out for code that relies on __uuidof(CoClassName) to return the GUID of the CoClass. Instead, code should use the CLSID_xxxx GUIDs generated by TLIBIMP for CoClasses.

That is, you would rewrite the above code as follows:


#include <stdio.h>
//#import "test.tlb"
#include "TestLibrary_TLB.h"
 
//using namespace TestLibrary;
 
int main()
{
//  GUID g = __uuidof(CoClass1);
  GUID g = CLSID_CoClass1;
  printf("GUID of CoClass1"
         " = {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
                              g.Data1, g.Data2, g.Data3,
                              g.Data4[0], g.Data4[1], 
                              g.Data4[2], g.Data4[3],
                              g.Data4[4], g.Data4[5], 
                              g.Data4[6], g.Data4[7]);
  return 0;
}

See Also