间接Typelib不能很好地从Debug dll导入

时间:2020-03-06 14:47:09  来源:igfitidea点击:

使用VC2005,我可以构建3个项目:

  • libA(包含一个typelib,结果为libA.dll):IDL有一行library libA {...
  • libB(包含一个导入libA的typelib,结果为libB.dll):IDL有一行importlib(" libA");
  • libC(导入libB):其中一个源文件包含#import <libB.dll>

#import <libB.dll>由编译器通过以下方式处理(根据文档):

  • 搜索%PATH%的目录
  • 搜索%LIB%的目录
  • 搜索"其他包含路径"(/ I编译器选项)

编译libC时,我可以看到cl.exe显然能够在可执行路径中找到libA.dll(使用Filemon.exe)

VC错误C4772:#import具有其他依赖项的typelib

但是,仍然找不到libA命名空间,并且所有对libA类型的引用都由__missing_type__替换。

(编辑)同时,我发现问题仅在使用调试dll时出现。

有人看过这个问题吗?解决了吗?

解决方案

我们是否明确设置项目的依赖项?换句话说,我们是否在IDE中设置了解决方案,使得项目C依赖于项目B,而项目B依赖于项目A?

我们是否正在使用libC的libA中定义的类型?如果是这样,我认为我们需要直接从libC导入libA,以便它了解libA的类型。 COM不会自动引用本身由另一个类型库引用的类型库。

我没有答案,但是我有几次这样的经历,我想分享一下我的所作所为。

在几个不相关的项目中,我遇到了相同的情况。在一个案例中,我尝试了将近一周的时间来解决依赖关系,但最终我不得不减少损失以保持进度。我最终在.tlh文件上使用#include(在DLL上执行导入将生成这些文件),然后使用"经典com" api调用获取指向.tlh文件内结构的指针。如果使用包装文件,该代码并不像使用时那样干净,但是它可以工作。

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

我们可以通过使用CComPtr包装器模板在超出范围时可靠地使用其析构函数进行释放,从而在某种程度上"消除丑闻":

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

请注意,_Application指针是使用.tlh文件中的结构之一的示例。

终于找到了!

在Visual Studio项目中,LibA中的A.idl文件的MkTypeLib Compatible设置为ON。这推翻了从A项目继承的行为。更糟的是,它仅在Debug配置中为ON。

结果是每个人

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

这导致tagE没有在生成的typelib中定义。当LibB做到了import(" A.dll")时,所有对tagE的引用都被替换为__missing_type__...。