views:

419

answers:

4

Using VC2005, I have 3 projects to build:

  • libA (contains a typelib, results in libA.dll): IDL has a line library libA { ...
  • libB (contains a typelib importing libA, results in libB.dll): IDL has a line importlib( "libA " );
  • libC (imports libB): one of the source files contains #import <libB.dll>

the #import <libB.dll> is handled by the compiler in the following way (according to documentation):

  1. search directories of %PATH%
  2. search directories of %LIB%
  3. search the "additional include paths" (/I compiler option)

When compiling libC, I can see that cl.exe clearly is able to find the libA.dll on the executable path (using Filemon.exe)

VC error C4772: #import of typelib with another dependency

However, still the libA namespace is not found and all references to libA types are replaced by __missing_type__

(edit) Meanwhile, I found out the problem only appears when using the debug dlls.

Anyone seen this problem before? And solved it?

+1  A: 

Are you explicitly setting the project's dependencies? In other words have you set up the solution in the IDE so that project C depends on project B, and project B depends on project A?

Jim Crafton
Initially, I had a solution containing all three projects plus the dependencies. This didn't work. Now I'm playing with the three project files, building them using the devenv.com command, one by one in the right order.
xtofl
+1  A: 

Are you using types defined in libA from libC? If so, I think that you need to directly import libA from libC so that it knows about libA's types. COM doesn't automatically reference the type libraries that are themselves referenced by another type library.

Andy
+1  A: 

I don't have an answer for you, but I had this experience several times and I'd like to share what I did.

On several unrelated projects, I had your same scenario. I tried for nearly a week in one case to resolve the dependencies, but I eventually had to cut my losses in order to stay on schedule. I ended up using an #include on the .tlh file (performing an import on the DLL will generate these), then using "classic com" api calls to get pointers to the structures within the .tlh files. The code is not as clean to work with as it would be if you could use the wrapper files, but it works.

IUnknown *lpUnk;
hr = CoCreateInstance(clsID, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void **)&lpUnk);
if (FAILED(hr)) throw SomeException;  

                                          //
_Application *app;                        //Address _Application  
hr = lpUnk->QueryInterface(__uuidof(_Application), (void **) &app);
lpUnk->Release();
if (FAILED(hr)) throw SomeException;  

                                          // Do stuff with the app object  
app->Release();                           // Then release

You can somewhat "de-uglify" this by using the CComPtr wrapper template to do the release reliably from with its destructor when it goes out of scope:

CComPtr<IUnknown> lpUnk;
hr = CoCreateInstance(clsID, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void **)lpUnk);
if (FAILED(hr)) throw SomeException;  
                                          //
CComPtr<_Application> app;                //Address _Application  
hr = lpUnk->QueryInterface(__uuidof(_Application), (void **) &app);
if (FAILED(hr)) throw SomeException;
                                         //
                                         // Do stuff with the app object

Note that the _Application pointer is an example of use of one of the structures from a .tlh file.

Steve
Thanks for the tip, but I'll pass this one... Since #importing the release dlls is working ok (even for debug builds).
xtofl
+1  A: 

Finally Found It!

In the Visual Studio project, the A.idl file in LibA had the MkTypeLib Compatible setting ON. This overruled the behaviour inherited from the A project. To make things worse, it was only ON in the Debug configuration.

The consequence was that for every

typedef [public] tagE enum { cE1, cE2 } eE;

This resulted in the tagE not being defined in the resulting typelib. When LibB did it's import( "A.dll" ), all references to tagE were replaced with __missing_type__...

xtofl