10000 ctypes FreeLibrary fails on Windows 64-bit · Issue #74472 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

ctypes FreeLibrary fails on Windows 64-bit #74472

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

Closed
giampaolo opened this issue May 5, 2017 · 4 comments
Closed

ctypes FreeLibrary fails on Windows 64-bit #74472

giampaolo opened this issue May 5, 2017 · 4 comments
Labels

Comments

@giampaolo
Copy link
Contributor
BPO 30286
Nosy @theller, @amauryfa, @abalkin, @giampaolo, @meadori, @eryksun

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = <Date 2017-05-07.12:21:44.269>
created_at = <Date 2017-05-05.18:59:55.331>
labels = ['ctypes', '3.7', 'invalid']
title = 'ctypes FreeLibrary fails on Windows 64-bit'
updated_at = <Date 2017-05-07.12:21:44.267>
user = 'https://github.com/giampaolo'

bugs.python.org fields:

activity = <Date 2017-05-07.12:21:44.267>
actor = 'giampaolo.rodola'
assignee = 'none'
closed = True
closed_date = <Date 2017-05-07.12:21:44.269>
closer = 'giampaolo.rodola'
components = ['ctypes']
creation = <Date 2017-05-05.18:59:55.331>
creator = 'giampaolo.rodola'
dependencies = []
files = []
hgrepos = []
issue_num = 30286
keywords = []
message_count = 4.0
messages = ['293135', '293136', '293149', '293188']
nosy_count = 6.0
nosy_names = ['theller', 'amaury.forgeotdarc', 'belopolsky', 'giampaolo.rodola', 'meador.inge', 'eryksun']
pr_nums = []
priority = 'normal'
resolution = 'not a bug'
stage = 'resolved'
status = 'closed'
superseder = None
type = None
url = 'https://bugs.python.org/issue30286'
versions = ['Python 3.4', 'Python 3.5', 'Python 3.6', 'Python 3.7']

@giampaolo
Copy link
Contributor Author
>>> import ctypes
>>> path = 'C:\\Python35-64\\vcruntime140.dll'
>>> cfile = ctypes.CDLL(path)
>>> cfile._handle
140736170229760
>>> ctypes.windll.kernel32.FreeLibrary(cfile._handle)
Traceback (most recent call last):
    ctypes.windll.kernel32.FreeLibrary(cfile._handle)
ctypes.ArgumentError: argument 1: <class 'OverflowError'>: int too long to convert

Everything is fine on 32-bit.

@giampaolo
Copy link
Contributor Author

http://stackoverflow.com/questions/23522055/error-when-unload-a-64bit-dll-using-ctypes-windll

Adding "ctypes.windll.kernel32.FreeLibrary.argtypes = [wintypes.HMODULE]" fixes the issue. This works:

import ctypes
from ctypes import wintypes
path = 'C:\\Python35-64\\vcruntime140.dll'
cfile = ctypes.CDLL(path)
print(cfile._handle)
ctypes.windll.kernel32.FreeLibrary.argtypes = [wintypes.HMODULE]
ctypes.windll.kernel32.FreeLibrary(cfile._handle)

@eryksun
Copy link
Contributor
eryksun commented May 6, 2017

It's documented that the default conversion for integer arguments is a 32-bit C int, which is also the default for result types. Whenever pointers (and Windows handles, which are sometimes 64-bit pointers, such as HMODULE values) are passed as arguments, integer values either need to be manually wrapped as ctypes pointer instances, or you need to set the function's argtypes to override the default behavior. Whenever a pointer is returned, you must set the function's restype.

BTW, _ctypes.FreeLibrary and _ctypes.dlclose already exist as built-in functions. They're just not imported to the main ctypes namespace, most likely because there's nothing in the design to prevent crashing Python if the shared library's reference count drops to 0 and the loader unmaps it from the process while there's remaining references to its address range.

Also, I recommend using ctypes.WinDLL and avoiding ctypes.windll, especially for common Windows APIs. It caches libraries, which cache function pointer instances. What if my library also uses it and customizes FreeLibrary.argtypes or FreeLibrary.errcheck in a way that breaks yours? It also doesn't allow setting use_last_error=True to capture the last error value in a thread-local variable that can be accessed via ctypes.get_last_error() and ctypes.set_last_error(). Capturing the last error value is a good idea in a high-level language like Python -- especially when working interactively in the REPL. This way ctypes.WinError(ctypes.get_last_error()) will reliable create an exception for whatever the error value was for the last FFI call.

@giampaolo
Copy link
Contributor Author

It's documented that the default conversion for integer arguments is a 32-bit C int. [...] Whenever a pointer is returned, you must set the function's restype.

OK, clear. Closing this out.

@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants
0