ynkdir / py-win32more

Python bindings for Win32 API generated from win32metadata.
MIT License
101 stars 12 forks source link

[ComPtr] Automatically release all object in a array #57

Open moi15moi opened 1 week ago

moi15moi commented 1 week ago

How can I set the parameter own=True when I create a array with a ComPtr ? My goal is to be sure to always release the object.

Currently, I do it like this, but it is clearly hacky:

def get_filepath_from_IDWriteFontFace(font_face: IDWriteFontFace) -> Set[str]:
    ...

    file_count = UInt32()
    hr = font_face.GetFiles(byref(file_count), None)
    if FAILED(hr):
        raise WinError(hr)

    font_files = (IDWriteFontFile * file_count.value)()
    hr = font_face.GetFiles(byref(file_count), font_files)
    if FAILED(hr):
        raise WinError(hr)

    for font_file in font_files:
            font_file._own = True
            ...
ynkdir commented 1 week ago

I could not find a good solution fot it.

Array doesn't call __del__() for element. And element of array can not have custom attribute like _own.

I think copying array to list is simple and explicit way for now.

font_files = [IDWriteFontFile(o.value, own=True) for o in font_files]

or we can create a list referring array memory.

def own_list(cls, size):
    def own(o):
        o._own = True
        return o
    return [own(o) for o in (cls * size)()]

...
font_files = own_list(IDWriteFontFile, file_count.value)
hr = font_face.GetFiles(byref(file_count), byref(font_files[0]))
moi15moi commented 1 week ago

comtypes (https://github.com/enthought/comtypes/issues/612) use metaclass to release the object Since ComPtr herit from c_void_p, I think we cannot use the same method, but it may gives you idea