
    ,VhD                     |   d Z g dZddlZddlmZmZmZmZm	Z	 ddl
mZmZ 	 ddlZed ZeZeZeZddlmZ eZn*ddlmc mZ  ej6                         Z[ej8                  Zd Zd	 Zg d
Zd Z G d de      Z  G d de       Z!i Z"ddZ#e$d Z$d Z% e%       Z&d Z'd Z(d Z)d Z*d Z+ddZd Zyy# e$ r dZY w xY w)a7  
============================
``ctypes`` Utility Functions
============================

See Also
--------
load_library : Load a C library.
ndpointer : Array restype/argtype with verification.
as_ctypes : Create a ctypes array from an ndarray.
as_array : Create an ndarray from a ctypes array.

References
----------
.. [1] "SciPy Cookbook: ctypes", https://scipy-cookbook.readthedocs.io/items/Ctypes.html

Examples
--------
Load the C library:

>>> _lib = np.ctypeslib.load_library('libmystuff', '.')     #doctest: +SKIP

Our result type, an ndarray that must be of type double, be 1-dimensional
and is C-contiguous in memory:

>>> array_1d_double = np.ctypeslib.ndpointer(
...                          dtype=np.double,
...                          ndim=1, flags='CONTIGUOUS')    #doctest: +SKIP

Our C-function typically takes an array and updates its values
in-place.  For example::

    void foo_func(double* x, int length)
    {
        int i;
        for (i = 0; i < length; i++) {
            x[i] = i*i;
        }
    }

We wrap it using:

>>> _lib.foo_func.restype = None                      #doctest: +SKIP
>>> _lib.foo_func.argtypes = [array_1d_double, c_int] #doctest: +SKIP

Then, we're ready to call ``foo_func``:

>>> out = np.empty(15, dtype=np.double)
>>> _lib.foo_func(out, len(out))                #doctest: +SKIP

)load_library	ndpointerc_intp	as_ctypesas_arrayas_ctypes_type    N)integerndarraydtypeasarray
frombuffer)	_flagdictflagsobjc                      t        d      )z
        Dummy object that raises an ImportError if ctypes is not available.

        Raises
        ------
        ImportError
            If ctypes is not available.

        zctypes is not available.)ImportError)argskwdss     ?/home/dcms/DCMS/lib/python3.12/site-packages/numpy/ctypeslib.py_dummyr   C   s     455    )intpc                 <   t        j                  |       } t        j                  |      }t         j                  j                  |       d   }|swddl}ddl}d}|j                  j                  d      rd}n|j                  j                  d      rd}| |z   g}|j                  d	      }||k(  s|j                  d| |z          n| g}t         j                  j                  |      }t         j                  j                  |      s t         j                  j                  |      }n|}|D ]W  }	t         j                  j                  ||	      }
t         j                  j                  |
      sC	 t        j                   |
   c S  t#        d
      # t"        $ r  w xY w)a
  
        It is possible to load a library using

        >>> lib = ctypes.cdll[<full_path_name>] # doctest: +SKIP

        But there are cross-platform considerations, such as library file extensions,
        plus the fact Windows will just load the first library it finds with that name.
        NumPy supplies the load_library function as a convenience.

        .. versionchanged:: 1.20.0
            Allow libname and loader_path to take any
            :term:`python:path-like object`.

        Parameters
        ----------
        libname : path-like
            Name of the library, which can have 'lib' as a prefix,
            but without an extension.
        loader_path : path-like
            Where the library can be found.

        Returns
        -------
        ctypes.cdll[libpath] : library object
           A ctypes library object

        Raises
        ------
        OSError
            If there is no library with the expected extension, or the
            library is defective and cannot be loaded.
           r   Nz.sodarwinz.dylibwinz.dll
EXT_SUFFIXzno file with expected extension)osfsdecodepathsplitextsys	sysconfigplatform
startswithget_config_varinsertabspathisdirdirnamejoinexistsctypescdllOSError)libnameloader_pathextr!   r"   base_extlibname_extso_extlibdirlnlibpaths              r   r   r   Z   s[   D ++g&kk+.ggw'* H||&&x0#((/!"X-.K--l;FX%""1g&67")Kggook2ww}}[)WW__[1F F 	Bggll62.Gww~~g&!;;w//		 788	  s   /FFc                 0    d}| D ]  }|t         |   z  } |S Nr   )r   )flaglistnumvals      r   _num_fromflagsr=      s)    
C y~Jr   )C_CONTIGUOUSF_CONTIGUOUSALIGNED	WRITEABLEOWNDATAWRITEBACKIFCOPYc                 `    g }t         D ]"  }t        |   }| |z  s|j                  |       $ |S N)
_flagnamesr   append)r;   reskeyvalues       r   _flags_fromnumrK      s8    
C #%KJJsO Jr   c                       e Zd Zed        Zy)_ndptrc                    t        |t              st        d      | j                  1|j                  | j                  k7  rt        d| j                  z        | j
                  1|j                  | j
                  k7  rt        d| j
                  z        | j                  :|j                  | j                  k7  r!t        dt        | j                        z        | j                  Q|j                  j                  | j                  z  | j                  k7  r!t        dt        | j                        z        |j                  S )Nzargument must be an ndarrayzarray must have data type %szarray must have %d dimension(s)zarray must have shape %szarray must have flags %s)
isinstancer
   	TypeError_dtype_r   _ndim_ndim_shape_shapestr_flags_flagsr;   rK   r,   )clsobjs     r   
from_paramz_ndptr.from_param   s    #w'9::;;"99+:S[[HII::!88szz)=

JKK;;"99+6S[[9IIJJ;;"YY]]S[[0S[[@6"3;;/0 1 1zzr   N)__name__
__module____qualname__classmethodr[    r   r   rM   rM      s     r   rM   c                   &    e Zd ZdZd Zed        Zy)_concrete_ndptrz
    Like _ndptr, but with `_shape_` and `_dtype_` specified.

    Notably, this means the pointer has enough information to reconstruct
    the array, which is not generally true.
    c                     | j                   S )z
        This method is called when this class is used as the .restype
        attribute for a shared-library function, to automatically wrap the
        pointer into an array.
        )contents)selfs    r   _check_retval_z_concrete_ndptr._check_retval_   s     }}r   c                    t        | j                  | j                  f      }t        j                  |j
                  z  }t        j                  | t        j                  |            j                  }t        ||      j                  d      S )z
        Get an ndarray viewing the data pointed to by this pointer.

        This mirrors the `contents` attribute of a normal ctypes pointer
        r   r   )axis)_dtyperQ   rT   r,   c_charitemsizecastPOINTERrd   r   squeeze)re   
full_dtype
full_ctypebuffers       r   rd   z_concrete_ndptr.contents   si     T\\4<<89
]]Z%8%88
T6>>*#=>GG&
3;;;CCr   N)r\   r]   r^   __doc__rf   propertyrd   r`   r   r   rb   rb      s"     	D 	Dr   rb   c           	         | t        |       } d}|t        |t              r|j                  d      }nKt        |t        t
        f      r|}t        |      }n't        |t              r|j                  }t        |      }|7	 |D cg c]   }|j                         j                         " }}t        |      }|	 t        |      }| |||f}	 t        |   S c c}w # t        $ r}t        d      |d}~ww xY w# t        $ r |f}Y @w xY w# t         $ r Y nw xY w| d}n-| j"                  t        t%        |             }n| j                  }||d|z  z  }||ddj'                  d |D              z   z  }||ddj'                  |      z   z  }| 	|t(        }	nt*        }	t-        d	|z  |	f| |||d
      }
|
t        |<   |
S )a:  
    Array-checking restype/argtypes.

    An ndpointer instance is used to describe an ndarray in restypes
    and argtypes specifications.  This approach is more flexible than
    using, for example, ``POINTER(c_double)``, since several restrictions
    can be specified, which are verified upon calling the ctypes function.
    These include data type, number of dimensions, shape and flags.  If a
    given array does not satisfy the specified restrictions,
    a ``TypeError`` is raised.

    Parameters
    ----------
    dtype : data-type, optional
        Array data-type.
    ndim : int, optional
        Number of array dimensions.
    shape : tuple of ints, optional
        Array shape.
    flags : str or tuple of str
        Array flags; may be one or more of:

        - C_CONTIGUOUS / C / CONTIGUOUS
        - F_CONTIGUOUS / F / FORTRAN
        - OWNDATA / O
        - WRITEABLE / W
        - ALIGNED / A
        - WRITEBACKIFCOPY / X

    Returns
    -------
    klass : ndpointer type object
        A type object, which is an ``_ndtpr`` instance containing
        dtype, ndim, shape and flags information.

    Raises
    ------
    TypeError
        If a given array does not satisfy the specified restrictions.

    Examples
    --------
    >>> clib.somefunc.argtypes = [np.ctypeslib.ndpointer(dtype=np.float64,
    ...                                                  ndim=1,
    ...                                                  flags='C_CONTIGUOUS')]
    ... #doctest: +SKIP
    >>> clib.somefunc(np.array([1, 2, 3], dtype=np.float64))
    ... #doctest: +SKIP

    N,zinvalid flags specificationanyz_%dd_xc              3   2   K   | ]  }t        |        y wrE   )rV   ).0ry   s     r   	<genexpr>zndpointer.<locals>.<genexpr>L  s     3SV3s   zndpointer_%s)rQ   rT   rR   rW   )rj   rO   rV   splitintr	   rK   r   r;   stripupper	ExceptionrP   r=   tuple_pointer_type_cacheKeyErrornamesidr*   rb   rM   type)r   rS   rU   rX   r;   ry   e	cache_keynamebaseklasss              r   r   r      s   j u CeS!KK$EW~.C"3'Ex())C"3'E;F49:q*:: !'C 	%LE
 eS)I"9--! ; F =>AEF  	HE	   }		 2e9~yyCHH3U3333CHHUO##U.$tg"#!!#$E
 &+	"LsN   C %C+C ;C8 D
 C 	C5$C00C58DD
	DDc                 8    |ddd   D ]  }|| z  } d| _          | S )z7 Create an ndarray of the given element type and shape N)r]   )element_typerU   dims      r   _ctype_ndarrayr   _  s3    2; 	+C-L&*L#	+ r   c                  n   t         } | j                  | j                  | j                  | j                  | j
                  | j                  | j                  | j                  | j                  | j                  | j                  | j                  | j                  g}|D ci c]  }t        |      | c}S c c}w )zX
        Return a dictionary mapping native endian scalar dtype to ctypes types
        )r,   c_bytec_shortc_intc_long
c_longlongc_ubytec_ushortc_uintc_ulongc_ulonglongc_floatc_doublec_boolrj   )ctsimple_typesctypes      r   _get_scalar_type_mapr   h  s     IIrzz288RYYJJRYY

BNNJJII	
 3??uu$???s   B2c                 D   | j                  d      j                  d      }| j                  d      }	 t        |   }|j
                  dk(  r|j                  }|S |j
                  dk(  r|j                  }|S # t        $ r }t        dj	                  |             d d }~ww xY w)NS=z Converting {!r} to a ctypes type><)newbyteorder_scalar_type_mapr   NotImplementedErrorformat	byteorder__ctype_be____ctype_le__)r   dtype_with_endiandtype_nativer   r   s        r   _ctype_from_dtype_scalarr   y  s    !..s3@@E))#.	$\2E &&#-&&E  ((C/&&E  	%299%@	s   	A6 6	B?BBc                 N    | j                   \  }}t        |      }t        ||      S rE   )subdtype_ctype_from_dtyper   )r   element_dtyperU   r   s       r   _ctype_from_dtype_subarrayr     s'    $~~u!-0eU++r   c           	         g }| j                   D ]4  }| j                  |   d d \  }}|j                  ||t        |      f       6 t	        |d       }t        |      dkD  rt        d |D              rd}g }|D ]8  \  }}}|j                  ||f       t        |t        j                  |            }: | j                  |k7  r.|j                  dt        j                  | j                  z  f       t        dt        j                  ft        |dd 	            S d}g }|D ]o  \  }}}||z
  }	|	dk  rt        d
      |	dkD  r$|j                  dt        j                  |	z  f       |j                  ||f       |t        j                  |      z   }q | j                  |z
  }	|	dkD  r$|j                  dt        j                  |	z  f       t        dt        j                   ft        |dd 	            S )N   c                     | d   S r9   r`   )fs    r   <lambda>z._ctype_from_dtype_structured.<locals>.<lambda>  s
    ad r   )rI   r   c              3   .   K   | ]  \  }}}|d k(    yw)r   Nr`   )r{   offsetr   r   s       r   r|   z/_ctype_from_dtype_structured.<locals>.<genexpr>  s     &Y7JvtUv{&Ys   r    union)_fields__pack_r]   zOverlapping fieldsstruct)r   fieldsrG   r   sortedlenallmaxr,   sizeofrl   rk   r   Uniondictr   	Structure)
r   
field_datar   field_dtyper   sizer   r   last_offsetpaddings
             r   _ctype_from_dtype_structuredr     s   
KK 	ND"',,t"4Ra"8Kvt->{-KLM	N
 JN;
z?Q3&Yj&Y#YDH'1 7#eu.4u!567
 ~~%V]]U^^%C DE &,,$!3   KH'1 <#e ;.Q;-.BCCQ;OOR)@$ABu.$v}}U';;< nn{2G{V]]W%< => 6#3#3"5t!8  r   c                 t    | j                   t        |       S | j                  t        |       S t	        |       S rE   )r   r   r   r   r   rh   s    r   r   r     s7    <<#/66^^'-e44+E22r   c                 *    t        t        |             S )a
  
        Convert a dtype into a ctypes type.

        Parameters
        ----------
        dtype : dtype
            The dtype to convert

        Returns
        -------
        ctype
            A ctype scalar, union, array, or struct

        Raises
        ------
        NotImplementedError
            If the conversion is not possible

        Notes
        -----
        This function does not losslessly round-trip in either direction.

        ``np.dtype(as_ctypes_type(dt))`` will:

        - insert padding fields
        - reorder fields to be sorted by offset
        - discard field titles

        ``as_ctypes_type(np.dtype(ctype))`` will:

        - discard the class names of `ctypes.Structure`\ s and
          `ctypes.Union`\ s
        - convert single-element `ctypes.Union`\ s into single-element
          `ctypes.Structure`\ s
        - insert padding fields

        Examples
        --------
        Converting a simple dtype:

        >>> dt = np.dtype('int8')
        >>> ctype = np.ctypeslib.as_ctypes_type(dt)
        >>> ctype
        <class 'ctypes.c_byte'>

        Converting a structured dtype:

        >>> dt = np.dtype([('x', 'i4'), ('y', 'f4')])
        >>> ctype = np.ctypeslib.as_ctypes_type(dt)
        >>> ctype
        <class 'struct'>

        )r   rj   rh   s    r   r   r     s    l !//r   c                     t        | t        j                        rV|t        d      t        j                  t        | j                  |            }t        j                  | |      j                  } t        |       S )a"  
        Create a numpy array from a ctypes array or POINTER.

        The numpy array shares the memory with the ctypes object.

        The shape parameter must be given if converting from a ctypes POINTER.
        The shape parameter is ignored if converting from a ctypes array
        z=as_array() requires a shape argument when called on a pointer)
rO   r,   _PointerrP   rn   r   _type_rm   rd   r   )rZ   rU   
p_arr_types      r   r   r   
  sd     c6??+}   szz5(IJJ++c:.77Cs|r   c                     | j                   }|d   rt        d      |d   dk7  rt        d      |d   \  }}|rt        d      t        |d         }t        ||d	         }|j	                  |      }| |_        |S )
zCreate and return a ctypes object from a numpy array.  Actually
        anything that exposes the __array_interface__ is accepted.strideszstrided arrays not supportedversion   z,only __array_interface__ version 3 supporteddatazreadonly arrays unsupportedtypestrrU   )__array_interface__rP   r   r   from_address__keep)rZ   aiaddrreadonlyctype_scalarresult_typeresults          r   r   r     s     $$i=:;;i=AJKKFh9:: &bm4$\2g;?))$/r   )NNNNrE   ),rs   __all__r   numpyr	   r
   r   rj   r   r   numpy._core.multiarrayr   r   r,   r   r   r   r   r   r   r   object_ndptr_basenumpy._core._internal_core	_internalnic_getintp_ctypec_void_pr=   rF   rK   rM   rb   r   r   r   r   r   r   r   r   r   r   r`   r   r   <module>r      s  2f 
  7 
>
6 LIH$K''S!F//KG9T,
[ *Df D<  rj 
@ ,-&,3l360r*C   Fs   B1 1B;:B;