在 IUnknown 中添加和发布,它们实际上做了什么?
addref and release in IUnknown, what do they actually do?
我一直试图让我的大脑在Windows中扩展外壳。需要实现的一些函数是 addref() 和 release()。它说,它会跟踪对象引用并在不使用时释放它们。
只是在一个简单的解释中,它实际上在跟踪什么?在我的想法中,你创建自己的对象,根据你的目的实现各种接口,然后让classfactory将对象返回到com引擎运行,除非我弄错了。
我只是在理解这个概念方面真的很慢。也是一步一步的过程,Windows com引擎加载shell扩展,从识别dll到实际执行再到卸载。请做一些简单的解释。问候
外壳扩展只是普通的 COM 对象。
接口(通常以大写 i 为前缀)基本上是一个协定。一个接口可以有一个或多个实现。
发布由对象/接口的"用户"在使用完后调用:
IWhatever*pW;
if (SUCCEEDED(CoCreateInstance(CLSID_Something, ..., IID_IWhatever, (void**) &pW)))
{
pW->DoWhateverThisThingDoes();
NotifyMyClients(pW);
pW->Release(); // Tell this instance that we are done with it
}
在前面的示例中,我们调用 Release 来指示我们不再需要此接口,但我们实际上不知道接口实例现在是否会被销毁。
如果我们想象NotifyMyClients
已知的客户端/插件/扩展之一是这样实现的:
class FooClient {
IWhatever*MyWhatever;
void FooClient::OnNotifyNewWhatever(IWhatever*p) // Somehow called by NotifyMyClients
{
p->AddRef(); // We want to use this object later even if everyone else are done with it
if (MyWhatever) MyWhatever->Release(); // Throw away the previous instance if we had one
MyWhatever = p;
SetTimer(...); // Activate timer so we can interact with MyWhatever later
}
FooClient::FooClient()
{
MyWhatever = 0;
}
FooClient::~FooClient()
{
if (MyWhatever) MyWhatever->Release();
}
};
创建对象的代码不需要知道其他代码对对象执行的操作,它只负责自己与对象的交互。
基本规则是:每次在对象上调用 AddRef 时调用 Release 一次。如果创建了对象实例,则还必须释放它。
用于实现 STA 接口的伪代码可能如下所示:
#include <Whatever.h> // The skeleton/contract for IWhatever
class Whatever : public IWhatever {
ULONG refcount;
Whatever() : refcount(1) {} // Instance refcount should start at 1
HRESULT QueryInterface(...) { ... }
ULONG AddRef() { return ++refcount; }
ULONG Release()
{
if (--refcount == 0) // Anyone still using me?
{
delete this; // Nope, I can destroy myself
return 0;
}
return refcount;
}
void DoWhateverThisThingDoes() { PerformMagic(this); }
};
必须在注册表中注册此特定 IWhatever 实现 (CLSID_Something) 的 CLSID,以便 COM 可以找到它。注册包括指向代码所在.DLL的路径。此.DLL必须导出DllGetClassObject
函数。
DllGetClassObject 分发其 IClassFactory 实现的实例,当 COM 请求一个新的 IWhatever 实例时,工厂只会调用new Whatever();
。
我没有介绍 QueryInterface,但它用于询问对象实例是否支持另一个接口。ICar
可能实现IVehicle
,但不是IBus
也不是ITrain
等。所有 COM 对象都支持 IUnknown 接口,所有其他接口都继承自 IUnknown。
不可能用一个答案来解释COM,但网上有很多介绍文章。
您可以使用/使用由Microsoft方和第三方创建的 shell 对象,也可以创建自己的文档接口实现。
如果我们以IContextMenu为例。在单个系统上可以有许多实现。资源管理器为每个已注册和适用的实例创建一个实例(文件扩展名与注册等匹配)IContextMenu 实现,当您右键单击某些内容并且每个实例将其菜单项添加到菜单中时。再次调用添加所选菜单项的实例以执行其操作,然后释放所有实例。
MSDN 具有此处最常用的扩展类型列表。如果你想写一个,编写 Shell 扩展的完整白痴指南是一个很好的起点。
只是一个简单的解释,它实际上在跟踪什么?
很简单,你说的:
它跟踪对象引用并在不使用时释放它们
它们用于跟踪正在使用的对对象的引用数。
调用 addref() 会增加引用计数,而 release() 会递减它。 你调用 addref() 以确保它知道你正在使用该对象,这样它就不会破坏它。 完成后,释放()告诉它您已完成对象。
一旦每个人都完成了对象的处理(引用计数下降到零),就可以销毁该对象。
请注意,获取接口引用(例如通过DllGetClassObject
) 将为您调用 addref(),因此您收到的接口引用的引用计数(至少)为 1。
- "delete"在 C++ 中实际上做了什么?
- 您好,我实际上想了解以下代码.有人可以详细说明代码它到底在做什么吗?为什么它会在第 31 行崩溃
- *(int*)&data[18]在这段代码中实际上做了什么?
- mOffsetMatrix在Assimp中实际上做了什么?
- 当我们在 C++ 中说"initialize the object"时,它实际上意味着什么?
- C++ 中向量的 .size() 实际上有什么作用?
- 'return *this'实际上做了什么?
- CPACK_DEB_PACKAGE_COMPONENT实际上做了什么
- 声明是否无效()合法,它实际上是什么?
- 在 IUnknown 中添加和发布,它们实际上做了什么?
- 实际上,什么是负数的模
- vk::D eviceQueueCreateFlags() 实际上做了什么?
- 什么时候 constexpr 实际上不是 constexpr
- C++:去引用实际上在做什么
- boost::asio::io_service::run() 实际上做了什么
- C 如果实际上是继承了类,则内部发生了什么
- 无法理解C++中的枚举,它们实际上是什么?
- 当调用带有警告"control reaches end of non-void function"的函数时,(实际上)会发生什么?
- 实际上什么返回类型有一个新的
- glutswapbuffers实际上做了什么