11"""create and manipulate C data types in Python"""
22
3- import os as _os , sys as _sys
3+ import os as _os
4+ import sys as _sys
5+ import sysconfig as _sysconfig
46import types as _types
57
68__version__ = "1.1.0"
3638 FUNCFLAG_USE_ERRNO as _FUNCFLAG_USE_ERRNO , \
3739 FUNCFLAG_USE_LASTERROR as _FUNCFLAG_USE_LASTERROR
3840
39- # TODO: RUSTPYTHON remove this
40- from _ctypes import _non_existing_function
41-
4241# WINOLEAPI -> HRESULT
4342# WINOLEAPI_(type)
4443#
@@ -110,7 +109,7 @@ class CFunctionType(_CFuncPtr):
110109 return CFunctionType
111110
112111if _os .name == "nt" :
113- from _ctypes import LoadLibrary as _dlopen
112+ from _ctypes import LoadLibrary as _LoadLibrary
114113 from _ctypes import FUNCFLAG_STDCALL as _FUNCFLAG_STDCALL
115114
116115 _win_functype_cache = {}
@@ -305,8 +304,9 @@ def create_unicode_buffer(init, size=None):
305304 raise TypeError (init )
306305
307306
308- # XXX Deprecated
309307def SetPointerType (pointer , cls ):
308+ import warnings
309+ warnings ._deprecated ("ctypes.SetPointerType" , remove = (3 , 15 ))
310310 if _pointer_type_cache .get (cls , None ) is not None :
311311 raise RuntimeError ("This type already exists in the cache" )
312312 if id (pointer ) not in _pointer_type_cache :
@@ -315,7 +315,6 @@ def SetPointerType(pointer, cls):
315315 _pointer_type_cache [cls ] = pointer
316316 del _pointer_type_cache [id (pointer )]
317317
318- # XXX Deprecated
319318def ARRAY (typ , len ):
320319 return typ * len
321320
@@ -347,52 +346,59 @@ def __init__(self, name, mode=DEFAULT_MODE, handle=None,
347346 use_errno = False ,
348347 use_last_error = False ,
349348 winmode = None ):
349+ class _FuncPtr (_CFuncPtr ):
350+ _flags_ = self ._func_flags_
351+ _restype_ = self ._func_restype_
352+ if use_errno :
353+ _flags_ |= _FUNCFLAG_USE_ERRNO
354+ if use_last_error :
355+ _flags_ |= _FUNCFLAG_USE_LASTERROR
356+
357+ self ._FuncPtr = _FuncPtr
350358 if name :
351359 name = _os .fspath (name )
352360
361+ self ._handle = self ._load_library (name , mode , handle , winmode )
362+
363+ if _os .name == "nt" :
364+ def _load_library (self , name , mode , handle , winmode ):
365+ if winmode is None :
366+ import nt as _nt
367+ winmode = _nt ._LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
368+ # WINAPI LoadLibrary searches for a DLL if the given name
369+ # is not fully qualified with an explicit drive. For POSIX
370+ # compatibility, and because the DLL search path no longer
371+ # contains the working directory, begin by fully resolving
372+ # any name that contains a path separator.
373+ if name is not None and ('/' in name or '\\ ' in name ):
374+ name = _nt ._getfullpathname (name )
375+ winmode |= _nt ._LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
376+ self ._name = name
377+ if handle is not None :
378+ return handle
379+ return _LoadLibrary (self ._name , winmode )
380+
381+ else :
382+ def _load_library (self , name , mode , handle , winmode ):
353383 # If the filename that has been provided is an iOS/tvOS/watchOS
354384 # .fwork file, dereference the location to the true origin of the
355385 # binary.
356- if name .endswith (".fwork" ):
386+ if name and name .endswith (".fwork" ):
357387 with open (name ) as f :
358388 name = _os .path .join (
359389 _os .path .dirname (_sys .executable ),
360390 f .read ().strip ()
361391 )
362-
363- self ._name = name
364- flags = self ._func_flags_
365- if use_errno :
366- flags |= _FUNCFLAG_USE_ERRNO
367- if use_last_error :
368- flags |= _FUNCFLAG_USE_LASTERROR
369- if _sys .platform .startswith ("aix" ):
370- """When the name contains ".a(" and ends with ")",
371- e.g., "libFOO.a(libFOO.so)" - this is taken to be an
372- archive(member) syntax for dlopen(), and the mode is adjusted.
373- Otherwise, name is presented to dlopen() as a file argument.
374- """
375- if name and name .endswith (")" ) and ".a(" in name :
376- mode |= ( _os .RTLD_MEMBER | _os .RTLD_NOW )
377- if _os .name == "nt" :
378- if winmode is not None :
379- mode = winmode
380- else :
381- import nt
382- mode = nt ._LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
383- if '/' in name or '\\ ' in name :
384- self ._name = nt ._getfullpathname (self ._name )
385- mode |= nt ._LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
386-
387- class _FuncPtr (_CFuncPtr ):
388- _flags_ = flags
389- _restype_ = self ._func_restype_
390- self ._FuncPtr = _FuncPtr
391-
392- if handle is None :
393- self ._handle = _dlopen (self ._name , mode )
394- else :
395- self ._handle = handle
392+ if _sys .platform .startswith ("aix" ):
393+ """When the name contains ".a(" and ends with ")",
394+ e.g., "libFOO.a(libFOO.so)" - this is taken to be an
395+ archive(member) syntax for dlopen(), and the mode is adjusted.
396+ Otherwise, name is presented to dlopen() as a file argument.
397+ """
398+ if name and name .endswith (")" ) and ".a(" in name :
399+ mode |= _os .RTLD_MEMBER | _os .RTLD_NOW
400+ self ._name = name
401+ return _dlopen (name , mode )
396402
397403 def __repr__ (self ):
398404 return "<%s '%s', handle %x at %#x>" % \
@@ -480,10 +486,9 @@ def LoadLibrary(self, name):
480486
481487if _os .name == "nt" :
482488 pythonapi = PyDLL ("python dll" , None , _sys .dllhandle )
483- elif _sys .platform == "android" :
484- pythonapi = PyDLL ("libpython%d.%d.so" % _sys .version_info [:2 ])
485- elif _sys .platform == "cygwin" :
486- pythonapi = PyDLL ("libpython%d.%d.dll" % _sys .version_info [:2 ])
489+ elif _sys .platform in ["android" , "cygwin" ]:
490+ # These are Unix-like platforms which use a dynamically-linked libpython.
491+ pythonapi = PyDLL (_sysconfig .get_config_var ("LDLIBRARY" ))
487492else :
488493 pythonapi = PyDLL (None )
489494
0 commit comments