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

Posted

技术标签:

【中文标题】不能从调试 dll 很好地导入间接 Typelib【英文标题】:Indirect Typelib not imported well from Debug dll 【发布时间】:2008-09-26 14:03:54 【问题描述】:

使用 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 of typelib 与另一个依赖项

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

(edit) 同时,我发现这个问题只在使用调试 dll 时出现。

以前有人见过这个问题吗?并解决了吗?

【问题讨论】:

【参考方案1】:

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

【讨论】:

最初,我有一个包含所有三个项目以及依赖项的解决方案。这没有用。现在我正在使用这三个项目文件,使用 devenv.com 命令以正确的顺序一一构建它们。【参考方案2】:

您是否使用 libC 中的 libA 中定义的类型?如果是这样,我认为您需要直接从 libC 导入 libA,以便它知道 libA 的类型。 COM 不会自动引用其他类型库引用的类型库。

【讨论】:

【参考方案3】:

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

在几个不相关的项目中,我遇到了与您相同的情况。在一个案例中,我尝试了将近一周的时间来解决依赖关系,但最终我不得不减少损失以保持进度。我最终在 .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 文件中的结构之一的示例。

【讨论】:

感谢您的提示,但我会通过这个...因为#importing 发布 dll 工作正常(即使是调试版本)。【参考方案4】:

终于找到了!

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

结果是每个

typedef [public] tagE enum  cE1, cE2  eE;

这导致tagE 未在生成的类型库中定义。当 LibB 使用 import( "A.dll" ) 时,所有对 tagE 的引用都被替换为 __missing_type__...

【讨论】:

以上是关于不能从调试 dll 很好地导入间接 Typelib的主要内容,如果未能解决你的问题,请参考以下文章

Window 7 上的 ATL COM DLL 注册无法更新 CLSID 部分,但 TypeLib 可以工作

(lat, lon) WKT 坐标不能用 st_transform 很好地重新投影

通过 talend 从 oracle 加载到 greenplum 时的数据不能很好地处理 CLOB 列

未捕获的错误:不能间接使用定义

DLL 函数调用的间接跳转

我如何调试在外部 C# 应用程序中 SWIGed 的 C++ DLL(不能从调试器启动)