我已阅读Marshal.GetIUnknownForObject
的文档,并说:
完成指针后,始终使用
Marshal.Release
减少引用计数。
我用一个COM对象编写了一个测试解决方案,我通过.NET使用它,我发现当使用wrapper到我的COM对象时,Marshal.GetIUnknownForObject
和Marshal.Release
都不会导致{我的COM对象的{1}}或AddRef
方法被调用。
这是怎么回事?
答案 0 :(得分:6)
等一下,我想我已经明白了。你正在制作一个COM对象,然后你围绕那个COM对象制作一个运行时可调用的包装器,然后你要求运行时可调用的包装器为它的朋克,然后你想知道为什么在那个朋克上调用release不会调用你的发布?这总结了你的问题吗?
如果是这样,你可能已经在问题中提到了所有这些细节,而不是让我们猜测。
那么,为什么你认为它会调用你的版本?它将调用运行时可调用包装器的Release 。包装器包装您的对象;这就是为什么它叫做包装。运行时可调用包装器不会需要来addref并在每次它被添加并释放时释放您的对象!为什么会这样?它需要让你的对象保持活着,它已经在你的对象上有一个引用;这足以使包裹的物体保持活力。为什么不必要的工作?
当你在COM对象周围有一个运行时可调用包装器时,你应该合理地期望对象的ref计数在对象的整个生命周期内是不变的。运行时接受一次ref,当RCW最后一次被垃圾收集或以其他方式释放时,它会释放ref并且对象会自行删除。
这样想。假设你说:
foo->bar = blah;
blah->AddRef();
blah得到addref'd,因为foo-> bar有一个对它的引用。现在你说:
abc->def = foo;
foo->AddRef();
这为foo添加了一个参考。它是否添加了参考等等?当然不是。为什么会这样? foo有一个基础; foo被abc保持活着的事实与blah无关。
这里也是一样的。你有:
wrapper = new RCW();
wrapper->wrapped = yourobject;
yourobject->AddRef();
这为你提供了一个参考资料。现在,如果你有
wrapper->QI(IUnknown, &punk)
它不会给你底层对象的朋克,它会给你包装器的朋克。如果你说
punk->AddRef();
没有addref底层对象,它addrefs包装器。
答案 1 :(得分:3)
Marshal.AddRef
和Marshal.Release
方法正在调用COM实例的COM AddRef和Release方法; Marshal.GetIUnknownForObject
可能会调用QueryInterface
,这意味着返回的AddRef
指针上有IUnknown
。
也许你的测试项目有点错误,可能在另一个COM实例上调用AddRef和Remove而不是你想要的那个?