a :jgMC@s`dZgdZddlZddlmZmZmZmZm Z ddl m Z m Z z ddl Z WneybdZ Yn0e durddZeZeZeZddlmZeZn*ddlmmZeZ[e jZd d Zd d Zgd ZddZGdddeZ Gddde Z!iZ"d(ddZ#e dur\ddZ$ddZ%e%Z&ddZ'ddZ(ddZ)d d!Z*d"d#Z+d)d$d%Zd&d'ZdS)*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 ndpointerc_intp as_ctypesas_arrayas_ctypes_typeN)integerndarraydtypeasarray frombuffer) _flagdictflagsobjcOs tddS)z Dummy object that raises an ImportError if ctypes is not available. Raises ------ ImportError If ctypes is not available. zctypes is not available.N) ImportError)argskwdsr9/usr/local/lib/python3.9/site-packages/numpy/ctypeslib.py_dummyCs r)intpc Cst|}t|}tj|d}|sddl}ddl}d}|jdrNd}n|jdr^d}||g}|d }||ks| d||n|g}tj |}tj |stj |}n|}|D]F} tj || } tj| rztj| WStyYq0qtd dS) a  It is possible to load a library using >>> lib = ctypes.cdll[] # 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. rNz.sodarwinz.dylibwinz.dll EXT_SUFFIXzno file with expected extension)osfsdecodepathsplitextsys sysconfigplatform startswithget_config_varinsertabspathisdirdirnamejoinexistsctypesZcdllOSError) ZlibnameZ loader_pathextrrZbase_extZ libname_extZso_extlibdirlnZlibpathrrrrZs8"          rcCsd}|D]}|t|7}q|SNr)r )Zflaglistnumvalrrr_num_fromflagssr1)Z C_CONTIGUOUSZ F_CONTIGUOUSZALIGNEDZ WRITEABLEZOWNDATAZWRITEBACKIFCOPYcCs,g}tD]}t|}||@r||q|SN) _flagnamesr append)r/reskeyvaluerrr_flags_fromnums  r8c@seZdZeddZdS)_ndptrcCst|tstd|jdur6|j|jkr6td|j|jdurZ|j|jkrZtd|j|jdur|j|jkrtdt |j|j dur|j j |j @|j krtdt |j |jS)Nzargument must be an ndarrayzarray must have data type %szarray must have %d dimension(s)zarray must have shape %szarray must have flags %s) isinstancer TypeError_dtype_r _ndim_ndim_shape_shapestr_flags_flagsr/r8r))clsobjrrr from_params*        z_ndptr.from_paramN)__name__ __module__ __qualname__ classmethodrFrrrrr9sr9c@s$eZdZdZddZeddZdS)_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. cCs|jS)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)selfrrr_check_retval_sz_concrete_ndptr._check_retval_cCsDt|j|jf}tj|j}t|t|j}t ||dj ddS)z Get an ndarray viewing the data pointed to by this pointer. This mirrors the `contents` attribute of a normal ctypes pointer r r)Zaxis) _dtyper<r?r)c_charitemsizecastPOINTERrLr Zsqueeze)rMZ full_dtypeZ full_ctypebufferrrrrLs z_concrete_ndptr.contentsN)rGrHrI__doc__rNpropertyrLrrrrrKsrKc Cs|durt|}d}|durt|tr2|d}n4t|ttfrN|}t|}nt|trf|j}t|}|durzdd|D}Wn.t y}zt d|WYd}~n d}~00t |}|durz t |}Wnt y|f}Yn0||||f}z t |WStyYn0|dur"d}n |jdur>> 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,cSsg|]}|qSr)stripupper.0xrrr .zndpointer..zinvalid flags specificationanyz_%dd_r]css|]}t|VqdSr2)rAr[rrr Lr_zndpointer..z ndpointer_%s)r<r?r=rB)rPr:rAsplitintrr8rr/ Exceptionr;r1tuple_pointer_type_cacheKeyErrornamesidr'rKr9type) r r>r@rCr/e cache_keynamebaseklassrrrrsf5                 rcCs&|dddD]}||}d|_q|S)z7 Create an ndarray of the given element type and shape N)rH)Z element_typer@dimrrr_ctype_ndarray_srsc CsJt}|j|j|j|j|j|j|j|j|j |j |j |j |j g }dd|DS)zX Return a dictionary mapping native endian scalar dtype to ctypes types cSsi|]}t||qSr)rP)r\ctyperrr sr_z(_get_scalar_type_map..)r)Zc_byteZc_shortZc_intZc_longZ c_longlongZc_ubyteZc_ushortZc_uintZc_ulongZ c_ulonglongZc_floatZc_doubleZc_bool)ctZ simple_typesrrr_get_scalar_type_maphsrwc Cs|dd}|d}z t|}Wn4tyZ}ztd|dWYd}~n d}~00|jdkrn|j}n|jdkr~|j}|S)NS=z Converting {!r} to a ctypes type><)Z newbyteorder_scalar_type_maprhNotImplementedErrorformat byteorderZ __ctype_be__Z __ctype_le__)r Zdtype_with_endianZ dtype_nativertrlrrr_ctype_from_dtype_scalarys    rcCs|j\}}t|}t||Sr2)subdtype_ctype_from_dtypers)r Z element_dtyper@rtrrr_ctype_from_dtype_subarrays rc Csg}|jD].}|j|dd\}}|||t|fq t|ddd}t|dkrtdd|Drd}g}|D](\}}}|||ft|t |}qt|j |kr|d tj |j ft d tj ft|ddd Sd}g}|D]^\}}}||} | dkrtd | dkr&|d tj | f|||f|t |}q|j |} | dkrl|d tj | ft d tjft|ddd SdS)NcSs|dSr.r)frrrr_z._ctype_from_dtype_structured..)r6rcss|]\}}}|dkVqdS)rNr)r\offsetrnrtrrrrbr_z/_ctype_from_dtype_structured..runion)_fields_Z_pack_rHzOverlapping fieldsstruct)rifieldsr4rsortedlenallmaxr)ZsizeofrRrQrkUniondictr}Z Structure) r Z field_datarnZ field_dtypersizerrtZ last_offsetpaddingrrr_ctype_from_dtype_structuredsH        rcCs0|jdurt|S|jdur$t|St|SdSr2)rrrrrrOrrrrs   rcCs tt|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 )rrPrOrrrrs&rcCsDt|tjr<|durtdtt|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) r:r)Z_Pointerr;rTrs_type_rSrLr )rEr@Z p_arr_typerrrrs rcCsp|j}|drtd|ddkr*td|d\}}|rBtdt|d}t||d }||}||_|S) zCreate and return a ctypes object from a numpy array. Actually anything that exposes the __array_interface__ is accepted.strideszstrided arrays not supportedversionz,only __array_interface__ version 3 supporteddatazreadonly arrays unsupportedZtypestrr@)Z__array_interface__r;rrsZ from_addressZ__keep)rEZaiaddrreadonlyZ ctype_scalarZ result_typeresultrrrrs    r)NNNN)N),rV__all__rnumpyrr r rPr r Znumpy._core.multiarrayr rr)rrrrrrrobjectZ _ndptr_baseZnumpy._core._internalZ_core _internalZnicZ_getintp_ctypeZc_void_pr1r3r8r9rKrgrrsrwr|rrrrrrrrrsL3     J  u  6 )