o
    %gI                     @   sN  d Z g dZddlZddlZddlmZmZ zddlZW n e	y'   dZY nw edu r?d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)	_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   N/root/parts/websockify/install/lib/python3.10/site-packages/numpy/ctypeslib.py_dummyA   s   
r   )intpc              	   C   s
  t | } t |}t j| d }|sFddl}ddl}d}|jdr'd}n|jdr/d}| | g}|d	}||ksE|	d| |  n| g}t j
|}t j|s\t j|}n|}|D ] }	t j||	}
t j|
rz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.
           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libpathr   r   r   r   X   s>   
"


r   c                 C   s   d}| D ]}|t | 7 }q|S Nr   )r   )flaglistnumvalr   r   r   _num_fromflags   s   r4   )C_CONTIGUOUSF_CONTIGUOUSALIGNED	WRITEABLEOWNDATAWRITEBACKIFCOPYc                 C   s,   g }t D ]}t| }| |@ r|| q|S N)
_flagnamesr   append)r2   reskeyvaluer   r   r   _flags_fromnum   s   
rA   c                   @   s   e Zd Zedd ZdS )_ndptrc                 C   s   t |tj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rB|j	| jkrBtdt
| j | jd urZ|jj| j@ | jkrZt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)
isinstancenpndarray	TypeError_dtype_dtype_ndim_ndim_shape_shapestr_flags_flagsr2   rA   r$   )clsobjr   r   r   
from_param   s"   



z_ndptr.from_paramN)__name__
__module____qualname__classmethodrR   r   r   r   r   rB      s    rB   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   sH   t | j| jf}tj|j }t| t|j	}t j
||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
        rH   r   )axis)rD   rH   rG   rK   r$   c_charitemsizecastPOINTERrX   
frombuffersqueeze)rY   
full_dtype
full_ctypebufferr   r   r   rX      s   z_concrete_ndptr.contentsN)rS   rT   rU   __doc__rZ   propertyrX   r   r   r   r   rW      s
    rW   c           
   
   C   s  | dur	t | } d}|durXt|tr|d}nt|tt jfr)|}t|}nt|tr5|j	}t|}|du rXz	dd |D }W n t
yS } ztd|d}~ww t|}|durozt|}W n tyn   |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 )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,c                 S   s   g | ]}|   qS r   )stripupper.0xr   r   r   
<listcomp>,      zndpointer.<locals>.<listcomp>zinvalid flags specificationanyz_%dd_rm   c                 s   s    | ]}t |V  qd S r;   )rM   rk   r   r   r   	<genexpr>J  s    zndpointer.<locals>.<genexpr>zndpointer_%s)rG   rK   rI   rN   )rD   rH   rC   rM   splitintintegerrA   r	   r2   	ExceptionrF   r4   tuple_pointer_type_cacheKeyErrornamesidr"   rW   rB   type)
rH   rJ   rL   rO   r2   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)rT   )element_typerL   dimr   r   r   _ctype_ndarray]  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   )rD   rH   )rl   ctyper   r   r   
<dictcomp>q  ro   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_mapf  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__)rH   dtype_with_endiandtype_nativer   r}   r   r   r   _ctype_from_dtype_scalarw  s$   


r   c                 C   s   | j \}}t|}t||S r;   )subdtype_ctype_from_dtyper   )rH   element_dtyperL   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 )N   c                 S   s   | d S r0   r   )fr   r   r   <lambda>  s    z._ctype_from_dtype_structured.<locals>.<lambda>)r?   r   c                 s   s    | ]
\}}}|d kV  qdS )r   Nr   )rl   offsetr   r   r   r   r   rr     s    z/_ctype_from_dtype_structured.<locals>.<genexpr>r    union)_fields__pack_rT   zOverlapping fieldsstruct)rz   fieldsr=   r   sortedlenallmaxr$   sizeofr^   r]   r|   Uniondictr   	Structure)
rH   
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

        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   rD   rH   r[   r   r   r   r     s   6r   c                 C   sF   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

        Examples
        --------
        Converting a ctypes integer array:

        >>> import ctypes
        >>> ctypes_array = (ctypes.c_int * 5)(0, 1, 2, 3, 4)
        >>> np_array = np.ctypeslib.as_array(ctypes_array)
        >>> np_array
        array([0, 1, 2, 3, 4], dtype=int32)

        Converting a ctypes POINTER:

        >>> import ctypes
        >>> buffer = (ctypes.c_int * 5)(0, 1, 2, 3, 4)
        >>> pointer = ctypes.cast(buffer, ctypes.POINTER(ctypes.c_int))
        >>> np_array = np.ctypeslib.as_array(pointer, (5,))
        >>> np_array
        array([0, 1, 2, 3, 4], dtype=int32)

        Nz=as_array() requires a shape argument when called on a pointer)rC   r$   _PointerrF   r`   r   _type_r_   rX   rD   asarray)rQ   rL   
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 )
a  
        Create and return a ctypes object from a numpy array.  Actually
        anything that exposes the __array_interface__ is accepted.

        Examples
        --------
        Create ctypes object from inferred int ``np.array``:

        >>> inferred_int_array = np.array([1, 2, 3])
        >>> c_int_array = np.ctypeslib.as_ctypes(inferred_int_array)
        >>> type(c_int_array)
        <class 'c_long_Array_3'>
        >>> c_int_array[:]
        [1, 2, 3]

        Create ctypes object from explicit 8 bit unsigned int ``np.array`` :

        >>> exp_int_array = np.array([1, 2, 3], dtype=np.uint8)
        >>> c_int_array = np.ctypeslib.as_ctypes(exp_int_array)
        >>> type(c_int_array)
        <class 'c_ubyte_Array_3'>
        >>> c_int_array[:]
        [1, 2, 3]

        strideszstrided arrays not supportedversion   z,only __array_interface__ version 3 supporteddatazreadonly arrays unsupportedtypestrrL   )__array_interface__rF   r   r   from_address__keep)rQ   aiaddrreadonlyctype_scalarresult_typeresultr   r   r   r   1  s   
r   )NNNNr;   )'rf   __all__r   numpyrD   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_pr4   r<   rA   rB   rW   rx   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sT    3J	
u	6	
9) 