o
    0c4D                     @   sb  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 zddlZW n ey1   dZY nw edu rIdd ZeZeZeZddlmZ eZnddlm  mZ e Z[ejZd	d
 Zdd Zg dZdd ZG dd deZ G dd de Z!i Z"d(ddZ#edurdd Z$dd Z%e% Z&dd Z'dd Z(dd Z)d d! Z*d"d# Z+d)d$d%Zd&d' ZdS dS )*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                  O   s   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kwds r   E/var/www/html/gps/gps/lib/python3.10/site-packages/numpy/ctypeslib.py_dummyC   s   
r   )intpc              	   C   s  t jdk rddl}|jddd t| } t|}tj| d }|sDddlm	} | }| | g}|d	d
}||ksC|
d| |  n| g}tj|}tj|sZtj|}n|}|D ] }	tj||	}
tj|
r~zt j|
 W   S  ty}    w q^td)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.
        z1.0.1r   NzAAll features of ctypes interface may not work with ctypes < 1.0.1   )
stacklevel   )get_shared_lib_extensionT)is_python_extzno file with expected extension)ctypes__version__warningswarnosfsdecodepathsplitextnumpy.distutils.misc_utilr   insertabspathisdirdirnamejoinexistscdllOSError)libnameloader_pathr   extr   so_extlibname_extso_ext2libdirlnlibpathr   r   r   r   Z   s>   
!



r   c                 C   s   d}| D ]}|t | 7 }q|S Nr   )r   )flaglistnumvalr   r   r   _num_fromflags   s   r9   )C_CONTIGUOUSF_CONTIGUOUSALIGNED	WRITEABLEOWNDATAWRITEBACKIFCOPYc                 C   s,   g }t D ]}t| }| |@ r|| q|S N)
_flagnamesr   append)r7   reskeyvaluer   r   r   _flags_fromnum   s   
rF   c                   @   s   e Zd Zedd ZdS )_ndptrc                 C   s   t |ts	td| jd ur|j| jkrtd| j | jd ur-|j| jkr-td| j | jd urA|j| jkrAtdt	| j | j
d urY|jj| j
@ | j
krYtdt| j
 |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_flagsr7   rF   r   )clsobjr   r   r   
from_param   s*   







z_ndptr.from_paramN)__name__
__module____qualname__classmethodrT   r   r   r   r   rG      s    rG   c                   @   s$   e Zd ZdZdd Zedd ZdS )_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                 C   s   | 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)selfr   r   r   _check_retval_   s   z_concrete_ndptr._check_retval_c                 C   sD   t | j| jf}tj|j }t| t|j}t	||dj
d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)_dtyperJ   rM   r   c_charitemsizecastPOINTERrZ   r   squeeze)r[   
full_dtype
full_ctypebufferr   r   r   rZ      s   z_concrete_ndptr.contentsN)rU   rV   rW   __doc__r\   propertyrZ   r   r   r   r   rY      s
    rY   c           
   
   C   s  | durt | } d}|durVt|tr|d}nt|ttfr'|}t|}nt|tr3|j}t|}|du rVz	dd |D }W n t	yQ } zt
d|d}~ww t|}|durmzt|}W n t
yl   |f}Y nw | |||f}zt| W S  ty   Y nw | du rd}n| jdurtt| }n| j}|dur|d| 7 }|dur|dd	d
d |D  7 }|dur|dd| 7 }| dur|durt}nt}td| |f| |||d}	|	t|< |	S )aF  
    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,c                 S   s   g | ]}|   qS r   )stripupper.0xr   r   r   
<listcomp>0  s    zndpointer.<locals>.<listcomp>zinvalid flags specificationanyz_%dd_ro   c                 s   s    | ]}t |V  qd S r@   )rO   rm   r   r   r   	<genexpr>N  s    zndpointer.<locals>.<genexpr>zndpointer_%s)rJ   rM   rK   rP   )r_   rH   rO   splitintr   rF   r   r7   	ExceptionrI   r9   tuple_pointer_type_cacheKeyErrornamesidr(   rY   rG   type)
r
   rL   rN   rQ   r7   e	cache_keynamebaseklassr   r   r   r      sn   5






r   c                 C   s&   |ddd D ]	}||  } d| _ q| S )z7 Create an ndarray of the given element type and shape N)rV   )element_typerN   dimr   r   r   _ctype_ndarraya  s   r   c                  C   sJ   t } | j| j| j| j| j| j| j| j| j	| j
| j| j| jg}dd |D S )zX
        Return a dictionary mapping native endian scalar dtype to ctypes types
        c                 S   s   i | ]}t ||qS r   )r_   )rn   ctyper   r   r   
<dictcomp>u  s    z(_get_scalar_type_map.<locals>.<dictcomp>)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_bool)ctsimple_typesr   r   r   _get_scalar_type_mapj  s   r   c              
   C   sx   |  d d}|  d}zt| }W n ty' } ztd| d d }~ww |jdkr2|j}|S |jdkr:|j}|S )NS=z Converting {!r} to a ctypes type><)newbyteorder_scalar_type_mapry   NotImplementedErrorformat	byteorder__ctype_be____ctype_le__)r
   dtype_with_endiandtype_nativer   r}   r   r   r   _ctype_from_dtype_scalar{  s$   


r   c                 C   s   | j \}}t|}t||S r@   )subdtype_ctype_from_dtyper   )r
   element_dtyperN   r   r   r   r   _ctype_from_dtype_subarray  s   

r   c           
      C   s  g }| j D ]}| j| d d \}}|||t|f qt|dd d}t|dkrltdd |D rld}g }|D ]\}}}|||f t|t	|}q:| j
|kr_|d	tj| j
 f td
tjft|dd dS d}g }|D ]-\}}}|| }	|	dk rtd|	dkr|d	tj|	 f |||f |t	| }qr| j
| }	|	dkr|d	tj|	 f tdtjft|dd dS )Nr   c                 S   s   | d S r5   r   )fr   r   r   <lambda>  s    z._ctype_from_dtype_structured.<locals>.<lambda>)rD   r   c                 s   s    | ]
\}}}|d kV  qdS )r   Nr   )rn   offsetr   r   r   r   r   rs     s    z/_ctype_from_dtype_structured.<locals>.<genexpr>r    union)_fields__pack_rV   zOverlapping fieldsstruct)rz   fieldsrB   r   sortedlenallmaxr   sizeofra   r`   r|   Uniondictr   	Structure)
r
   
field_datar   field_dtyper   sizer   r   last_offsetpaddingr   r   r   _ctype_from_dtype_structured  sH   


r   c                 C   s,   | j d ur	t| S | jd urt| S t| S r@   )r   r   r   r   r   r]   r   r   r   r     s
   

r   c                 C   s   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

        )r   r_   r]   r   r   r   r     s   &r   c                 C   sD   t | tjr|du rtdtt| j|}t| |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
        Nz=as_array() requires a shape argument when called on a pointer)
rH   r   _PointerrI   rc   r   _type_rb   rZ   r   )rS   rN   
p_arr_typer   r   r   r     s   	r   c                 C   sp   | j }|d rtd|d dkrtd|d \}}|r!tdt|d }t||d	 }||}| |_|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typestrrN   )__array_interface__rI   r   r   from_address__keep)rS   aiaddrreadonlyctype_scalarresult_typeresultr   r   r   r     s   
r   )NNNNr@   ),rh   __all__r   numpyr   r	   r
   r_   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_pr9   rA   rF   rG   rY   rx   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sT    3L	
u	6	
) 