【问题标题】:How to use COM dll in my C++ program如何在我的 C++ 程序中使用 COM dll
【发布时间】:2011-01-23 13:44:15
【问题描述】:

我希望在我的 C++ 库中使用 COM dll。 我想到的方法是#import dll 的 .tlb 文件,我这样做了:

#import "mycom.tlb" no_namespace

问题是,我不太清楚在哪里放置这个声明。它应该在H文件还是CPP文件中?或者可能是 stdafx.h 文件? 我试着把它放在 .cpp 文件中,只是为了测试。

在 H 文件中我声明了这个成员:

ILogicSecuredPtr m_pbLogic;

(其中 ILogicSecured 是我想在我的 COM dll 中使用的接口)

然后我在构造函数中添加了这个来实例化接口:

CoInitialize(NULL);
m_pbLogic(__uuidof(LogicSecured)); 

(其中 LogicSecured 是实现接口的对象的名称)

在我添加的析构函数中:

CoUninitialize();

但是,无论我尝试将#import 声明放在哪里,这都不会编译。 它只是无法识别 ILogicSecured 对象。 我在 H 文件中收到此错误:

Error   2   error C2146: syntax error : missing ';' before identifier 'm_pbLogic'

我还应该提到,当我在 ILogicSecuredPtr 声明上按 F12(在 Visual Studio 中)时,它会将我带到 tlh 文件就好了。所以我知道它可以识别它。

我在这里做错了什么?

非常感谢。 罗伊

【问题讨论】:

    标签: c++ dll com


    【解决方案1】:

    问题在于,当编译器解析 .h 文件时,它还没有看到 #import。由于您的项目很小,因此最好将#import 放入stdafx.h

    当您按 F12 时,Visual Studio 使用 Intellisence 数据库信息,这些信息是按可能不同于编译顺序的顺序解析所有源而形成的。因此,让 Intellisence 知道某些东西在哪里声明并且编译器不会同时编译它是很典型的。

    【讨论】:

    • 我可以把情节加粗一点吗?如果我尝试将 #import 添加到 stdafx.h 文件中,则 m_pbLogic(__uuidof(LogicSecured));一段代码无法编译,说 Error 18 error C2064: term does not evaluate to a functiontaking 1 arguments
    • 没错——你尝试在构造函数体内调用成员变量构造函数——这是不允许的。您应该改用 IWhateverPtr 的 CreateInstance() 方法。
    • 感谢您的快速回复。您能否提供一个模拟示例,说明如何在我的情况下调用 CreateInstance?以及放置在哪里?谢谢
    • 调用 m_pbLogic.CreateInstance( __uuidof(LogicSecured) ) 而不是尝试调用 m_pbLogic(...) - 它将返回一个 HRESULT - 使用 FAILED() 宏检查它 - 如果调用失败相应地作出反应- 抛出异常什么的。
    • 谢谢。还有一件事,在我的 .h 文件中,我将成员定义为: ILogicSecuredPtr m_pbLogic;在我尝试按照你所说的做的 cpp 文件中,它说 m_pbLogic 是未定义的,并且我在 .h 文件中也出现错误。我不能将 IWhateverPtr 定义为 .h 文件中的成员吗??
    【解决方案2】:

    如果导入 dll 或 tlb 文件,预处理器会生成一个 tlh 和一个 tli 文件。 如果 tlb 稳定,您还可以生成这两个文件并包含 tlh 标头,就像它是普通标头一样。

    所以答案是把 #import 放在你要放置标题的地方,因为它被转换为 tlh 文件的包含。

    我通过以下方式使用它,使自己独立于 MSADO15.dll 的位置,并将 tlh 文件添加到我的 subversion 中。

    #ifndef __ADO__H
    #define __ADO__H
    
    #ifdef REBUILD_ADO_HEADER
    #import "C:\Programme\Gemeinsame Dateien\system\ado\MSADO15.DLL" rename_namespace("MyAdoNamespace") rename("EOF","EndOfFile")
    #else // REBUILD_ADO_HEADER
    #include "MSADO15.tlh"
    #endif // REBUILD_ADO_HEADER
    
    // Define ADO Namespace as global
    using namespace MyAdoNamespace;
    
    #endif // __ADO__H
    

    【讨论】:

      【解决方案3】:

      除了您遇到的编译问题外,此设计还有其他问题。

      通常,C++ 库不应在 COM 未创建的线程上初始化 COM。这可能会导致一些令人讨厌的、难以调试的副作用。考虑更新您的库的接口规范,以指示使用某些方法或对象需要初始化 COM。您还应该指定所需的线程模型(STA、Free)。

      也就是说,您需要注意的另一件事是在您的智能指针超出范围之前调用 CoUnitialize()。这也可能导致一些难以调试的副作用。如果在包含 COM 智能指针的对象的析构函数中调用 CoUnitialize(),则需要在调用 CoUnitialize() 之前显式释放和分离指针。

      玩得开心!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-04
        • 2011-05-05
        • 2023-03-05
        • 2015-02-22
        • 2011-09-26
        • 2013-02-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多