pywin32
pywin32 copied to clipboard
SAFEARRAY Leaks IUnknown References
- Expected behavior and actual behavior.
When calling a COM method that returns a SAFEARRAY of newly created IUnknown pointers, I expect the reference count of the interfaces to be 1. Instead, the reference count of each element is 3. When the objects are garbage collected, the reference counts are reduced to 2. Unless the user manually calls Release()
twice on each element, the references are leaked. I believe this issue is related to #640.
- Steps to reproduce the problem.
I built and registered the following simple interface and class:
using System;
using System.Runtime.InteropServices;
namespace Example
{
[ComVisible(true)]
[Guid("E69FBDC1-6ADE-47CE-A642-F3795FE95ADD")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IExample
{
void GetNew(out IExample[] obj);
}
[ComVisible(true)]
[Guid("E3A22792-2109-4086-AB1E-49AEEDF2EDF9")]
[ClassInterface(ClassInterfaceType.None)]
public class Example : IExample
{
public void GetNew(out IExample[] obj)
{
obj = new[] { new Example() };
}
}
}
Then ran this script in Python 3.6:
import win32com.client
import ctypes.wintypes
import pythoncom
example = win32com.client.dynamic.DumbDispatch("Example.Example")
variant = win32com.client.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_ARRAY | pythoncom.VT_UNKNOWN, [])
example.GetNew(variant)
unknown = variant.value[0]
address = ctypes.c_void_p(int(repr(unknown).split()[-1][:-1], 16))
add_ref = ctypes.WINFUNCTYPE(ctypes.wintypes.ULONG)(1, "AddRef")
release = ctypes.WINFUNCTYPE(ctypes.wintypes.ULONG)(2, "Release")
add_ref(address)
count = release(address)
print(count)
Here is the result:
3
Process finished with exit code 0
- Version of Python and pywin32
Python 3.6 & pywin32 303