通常,您将使用CoCreateInstance()
从 COM DLL 实例化对象。执行此操作时,无需像处理普通 DLL 那样首先加载 DLL 并获取 proc 地址。这是因为 Windows “知道” COM DLL 实现的类型、实现它们的 DLL 以及如何实例化它们。(当然假设 COM DLL 已注册,通常是这样)。
假设您有一个带有要使用的 IDog 接口的 COM DLL。在这种情况下,
狗.idl
interface IDog : IUnknown
{
HRESULT Bark();
};
coclass Dog
{
[default] Interface IDog;
};
我的代码.cpp
IDog* piDog = 0;
CoCreateInstance(CLSID_DOG, 0, CLSCTX_INPROC_SERVER, IID_IDOG, &piDog); // windows will instantiate the IDog object and place the pointer to it in piDog
piDog->Bark(); // do stuff
piDog->Release(); // were done with it now
piDog = 0; // no need to delete it -- COM objects generally delete themselves
然而,所有这些内存管理的东西都可能变得很糟糕,而且 ATL 提供了智能指针,使实例化和管理这些对象的任务变得更容易一些:
CComPtr<IDog> dog;
dog.CoCreateInstance(CLSID_DOG);
dog->Bark();
编辑:
当我在上面说:
Windows“知道” COM DLL 实现的类型 [...以及] 它们在什么 DLL 中实现
...我真的掩盖了 Windows 是如何知道这一点的。这不是魔法,尽管起初它可能看起来有点神秘。
COM 库带有类型库,其中列出了库提供的接口和 CoClass。这个类型库在您的硬盘驱动器上以文件的形式出现——通常它直接嵌入到与库本身相同的 DLL 或 EXE 中。通过查看 Windows 注册表,Windows 知道在哪里可以找到类型库和 COM 库本身。注册表中的条目告诉 Windows DLL 在硬盘上的位置。
当您调用 时CoCreateInstance
,Windows 会在 Windows 注册表中查找 clsid,找到相应的 DLL,加载它,并在 DLL 中执行实现 COM 对象的适当代码。
此信息如何进入 Windows 注册表?安装 COM DLL 时,它会被注册。这通常是通过运行regsvr32.exe来完成的,它反过来将您的 DLL 加载到内存中并调用一个名为DllRegisterServer
. 该功能在您的 COM 服务器中实现,将必要的信息添加到注册表。如果您使用 ATL 或其他 COM 框架,这可能是在后台完成的,因此您不必直接与注册表交互。 DllRegisterServer
只需要在安装时调用一次。
如果您尝试通过/进程调用CoCreateInstance
尚未注册的 COM 对象,则会失败并显示以下错误:regsvr32
DllRegisterServer
CoCreateInstance
未注册课程
幸运的是,解决此问题的方法是简单地调用regsvr32
您的 COM 服务器,然后再试一次。