[issue39243] CDLL __init__ no longer supports name being passed as None when the handle is not None

Eryk Sun report at bugs.python.org
Wed Jan 8 00:23:17 EST 2020


Eryk Sun <eryksun at gmail.com> added the comment:

I'd like to match POSIX here by supporting path-like names. Also, I think it would be cleaner to split out the platform-specific work into a separate _load_library method, like how subprocess.Popen is designed, and to stop pretending that WINAPI LoadLibraryEx is POSIX dlopen. For example:

    if _os.name == "nt":
        import nt as _nt
        from _ctypes import LoadLibrary as _LoadLibrary
        from _ctypes import FUNCFLAG_STDCALL as _FUNCFLAG_STDCALL
        # ...
    else:
        from _ctypes import dlopen as _dlopen

    # ...

    class CDLL:
        # ...
        
        def __init__(self, name, mode=DEFAULT_MODE, handle=None,
                     use_errno=False, use_last_error=False, winmode=None):

            class _FuncPtr(_CFuncPtr):
                _restype_ = self._func_restype_
                _flags_ = self._func_flags_
                if use_errno:
                    _flags_ |= _FUNCFLAG_USE_ERRNO
                if use_last_error:
                    _flags_ |= _FUNCFLAG_USE_LASTERROR

            self._FuncPtr = _FuncPtr
            self._name = name
            if handle is None:
                self._handle = self._load_library(name, mode, winmode)
            else:
                self._handle = handle

        if _os.name == "nt":
            def _load_library(self, name, mode, winmode):
                if winmode is None:
                    winmode = _nt._LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
                if name:
                    name = _os.fsdecode(name)
                    # WINAPI LoadLibrary searches for a DLL if the given name
                    # is not fully qualified with an explicit drive. For POSIX
                    # compatibility, and because the DLL search path no longer
                    # contains the working directory, begin by fully resolving
                    # any name that contains a path separator.
                    if '/' in name or '\\' in name:
                        name = _nt._getfullpathname(name)
                        # Given a fully-qualified DLL name, allow loading
                        # dependents from its directory.
                        winmode |= _nt._LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
                return _LoadLibrary(name, winmode)

        else:
            def _load_library(self, name, mode, winmode):
                if _sys.platform.startswith("aix"):
                    # When the name contains ".a(" and ends with ")", for example,
                    # "libFOO.a(libFOO.so)" - this is taken to be an 
                    # archive(member) syntax for dlopen(), and the mode is
                    # adjusted. Otherwise, name is presented to dlopen() as a
                    # file argument.
                    if name and name.endswith(")") and ".a(" in name:
                        mode |= _os.RTLD_MEMBER | _os.RTLD_NOW
                return _dlopen(name, mode)

----------
nosy: +eryksun
stage:  -> test needed

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue39243>
_______________________________________


More information about the Python-bugs-list mailing list