如何在我的C++程序中使用COM dll

7

我希望在我的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'

我还应该提到,当我在Visual Studio中按F12()对ILogicSecuredPtr声明进行操作时,它可以很好地带我到tlh文件。所以我知道它被识别了。

我在这里做错了什么?

非常感谢。 Roey

3个回答

3
问题在于编译器解析.h文件时尚未看到#import。由于您的项目很小,最好将#import放入stdafx.h中。 当您按下F12键时,Visual Studio使用Intellisence数据库信息,该信息是通过解析所有源而形成的,可能与编译顺序不同。 因此,通常情况下,Intellisence知道某个声明的位置,而编译器同时不会对其进行编译。

我能稍微增加一下情节吗? 如果我尝试将 #import 添加到 stdafx.h 文件中,那么代码片段 m_pbLogic(__uuidof(LogicSecured)); 就无法编译,会出现错误 18 error C2064: term does not evaluate to a function taking 1 arguments。 - Roey
1
没错 - 你试图在构造函数体内调用成员变量的构造函数 - 这是不允许的。你应该使用IWhateverPtr的CreateInstance()方法。 - sharptooth
感谢您的快速回复。 您能否提供一个模拟示例,说明如何在我的情况下调用CreateInstance?以及在哪里放置它? - Roey
2
调用m_pbLogic.CreateInstance(__uuidof(LogicSecured)),而不是尝试调用m_pbLogic(...) - 它将返回一个HRESULT - 使用FAILED()宏检查它 - 如果调用失败,请相应地做出反应 - 抛出异常或其他操作。 - sharptooth
谢谢。还有一件事,在我的.h文件中,我定义了一个成员: ILogicSecuredPtr m_pbLogic;但是在我尝试按照您说的做的cpp文件中,它说m_pbLogic未定义,并且我在.h文件中也遇到了错误。 我不能在.h文件中定义IWhateverPtr作为成员吗? - Roey
你是否将头文件包含到 cpp 文件中了? - sharptooth

2
如果您导入dll或tlb文件,预处理器会生成tlh和tli文件。如果tlb是稳定的,您也可以生成这两个文件,并将tlh头文件包含在普通头文件中。
因此,答案是将#import放置在您将放置头文件的位置,因为它被转换为对tlh文件的包含。
我以以下方式使用它,使自己独立于MSADO15.dll的位置,并将tlh文件添加到我的子版本控制系统中。
#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

1

除了您遇到的编译问题之外,这个设计还存在其他问题。

一般来说,C++库不应该在它没有创建的线程上初始化COM。这可能会引起一些难以调试的恶性副作用。考虑更新您的库的接口规范,以指示某些方法或对象的使用需要初始化COM。您还应该指定所需的线程模型(STA、Free)。

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

祝愉快!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接