通常,您将使用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 对象,则会失败并显示以下错误:regsvr32DllRegisterServerCoCreateInstance
未注册课程
幸运的是,解决此问题的方法是简单地调用regsvr32您的 COM 服务器,然后再试一次。