Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The errors that occur when replacing ctypes.windll.foobar/ctypes.WinDLL("foobar") with ctypes.oledll.foobar/ctypes.OleDLL("foobar") #129010

Open
junkmd opened this issue Jan 19, 2025 · 4 comments
Labels
type-bug An unexpected behavior, bug, or error

Comments

@junkmd
Copy link
Contributor

junkmd commented Jan 19, 2025

Bug report

Bug description:

In enthought/comtypes#735, @moi15moi suggested avoiding the use of shared DLL objects, and work was attempted to implement this.

Replacing windll.foobar with WinDLL("foobar") and oledll.foobar with OleDLL("foobar") seemed like the appropriate approach.
However, when using OleDLL("foobar"), behavior like the one described in this comment occurred.

For the parts where oledll.foobar was originally used, I think it would be better to use OleDLL("foobar").
What do you think?

I think it's better to only keep OleDLL or WinDLL to have more consistent code. Having both of them is pretty useless since I specify the argtypes and restype for each function.

I choosed WinDLL because I observate weird behaviour with OleDLL. For example, for this line, if I change windll.oleaut32.SysAllocStringLen to _oleaut32.SysAllocStringLen, I get this error when I run the tests:

File "C:\Users\moi15moi\Documents\GitHub\comtypes\comtypes\test\test_showevents.py", line 24, in comtypes.test.test_showevents.ShowEventsExamples.StdFont_ShowEvents
Failed example:
    font.Name = 'Arial'
Exception raised:
    Traceback (most recent call last):
      File "C:\Users\moi15moi\AppData\Local\Programs\Python\Python311\Lib\doctest.py", line 1353, in __run
        exec(compile(example.source, filename, "single",
      File "<doctest comtypes.test.test_showevents.ShowEventsExamples.StdFont_ShowEvents[5]>", line 1, in <module>
        font.Name = 'Arial'
        ^^^^^^^^^
      File "C:\Users\moi15moi\Documents\GitHub\comtypes\comtypes\_post_coinit\_cominterface_meta_patcher.py", line 33, in __setattr__
        object.__setattr__(self, self.__map_case__.get(name.lower(), name), value)
      File "C:\Users\moi15moi\Documents\GitHub\comtypes\comtypes\_memberspec.py", line 514, in fset
        return obj.Invoke(memid, value, _invkind=invkind)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "C:\Users\moi15moi\Documents\GitHub\comtypes\comtypes\automation.py", line 879, in Invoke
        dp = self.__make_dp(_invkind, *args)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "C:\Users\moi15moi\Documents\GitHub\comtypes\comtypes\automation.py", line 854, in __make_dp
        array[i].value = a
        ^^^^^^^^^^^^^^
      File "C:\Users\moi15moi\Documents\GitHub\comtypes\comtypes\automation.py", line 290, in _set_value
        self._.c_void_p = _SysAllocStringLen(value, len(value))
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "_ctypes/callproc.c", line 1000, in GetResult
    OverflowError: Python int too large to convert to C long

I am unsure why this issue only occurs with OleDLL, but it seems very strange to me. According to the ctypes documentation, the only difference between OleDLL and WinDLL is the default restype: HRESULT for OleDLL and int for WinDLL. However, there must be a more significant underlying difference, as WinDLL does not fail under the same circumstances.

I had assumed that the only difference between oledll.foobar and OleDLL("foobar") was whether or not they were shared. (Edited: I was confused. See #129010 (comment))
Could the cause of this behavior lie within the C extension or the cffi layer?

(See also #129010 (comment) as a minimal reproducer.)

CPython versions tested on:

3.11

Operating systems tested on:

Windows

@junkmd junkmd added the type-bug An unexpected behavior, bug, or error label Jan 19, 2025
@moi15moi
Copy link

I had assumed that the only difference between oledll.foobar and OleDLL("foobar") was whether or not they were shared.

I think you are a bit confused. The issue occurs when we replace windll with OleDLL. It also occurs with oledll.

@junkmd
Copy link
Contributor Author

junkmd commented Jan 19, 2025

If that’s the case, I was certainly confused.

As mentioned in this comment, comtypes uses both oledll.ole32 and windll.ole32.
In the project, there are use cases where the returned HRESULT is not referenced even when a function returns it, so it’s unclear what the original intent was in distinguishing between these two.

Therefore, if the goal is to stop the side effects of shared DLL objects, I think that it makes sense to ensure that WinDLL and OleDLL can coexist.
For now, I believe replacing oledll.foobar with OleDLL("foobar") should suffice.
Whether or not to unify these into one approach should fall outside the scope of enthought/comtypes#735.

In any case, this does not seem like a topic that should be addressed in cpython.
I will close this issue.

@junkmd junkmd closed this as not planned Won't fix, can't repro, duplicate, stale Jan 19, 2025
@moi15moi
Copy link

I don't follow you. It still seems to be a bug for cpython.

Here is a smaller sample to reproduce the problem with OleDLL:

OleDLL sample
from ctypes import OleDLL, c_uint, c_void_p, c_wchar_p

oleaut32 = OleDLL("oleaut32")

SysAllocStringLen = oleaut32.SysAllocStringLen
SysAllocStringLen.argtypes = c_wchar_p, c_uint
SysAllocStringLen.restype = c_void_p

result = SysAllocStringLen("example", 2)

Here is the Traceback:

Traceback (most recent call last):
  File "c:\Users\moi15moi\Desktop\Untitled-1.py", line 9, in <module>
    result = SysAllocStringLen("example", 2)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "_ctypes/callproc.c", line 1000, in GetResult
OverflowError: Python int too large to convert to C long

Here is the exact same code except I replaced OleDLL with WinDLL:

WinDLL sample
from ctypes import WinDLL, c_uint, c_void_p, c_wchar_p

oleaut32 = WinDLL("oleaut32")

SysAllocStringLen = oleaut32.SysAllocStringLen
SysAllocStringLen.argtypes = c_wchar_p, c_uint
SysAllocStringLen.restype = c_void_p

result = SysAllocStringLen("example", 2)

There isn't any exception raised.

Tested on Python 3.11.7

@junkmd
Copy link
Contributor Author

junkmd commented Jan 19, 2025

#129010 (comment)

Ah, I finally understand now.
Sorry for all the back and forth.

Indeed, this is not limited to an issue with comtypes; it seems to be a bugfix that should be addressed in cpython or mentioned in the documentation.

I will reopen this issue.

@junkmd junkmd reopened this Jan 19, 2025
@junkmd junkmd changed the title The errors that occur when replacing ctypes.oledll.foobar with ctypes.OleDLL("foobar") The errors that occur when replacing ctypes.oledll.foobar/ctypes.OleDLL("foobar") with ctypes.oledll.foobar/ctypes.OleDLL("foobar") Jan 19, 2025
@junkmd junkmd changed the title The errors that occur when replacing ctypes.oledll.foobar/ctypes.OleDLL("foobar") with ctypes.oledll.foobar/ctypes.OleDLL("foobar") The errors that occur when replacing ctypes.windll.foobar/ctypes.WinDLL("foobar") with ctypes.oledll.foobar/ctypes.OleDLL("foobar") Jan 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

2 participants