@@ -38,7 +38,7 @@ from cpython.buffer cimport (
3838from cpython.bytes cimport PyBytes_FromStringAndSize
3939from libc.stdint cimport uint32_t
4040from libc.stdlib cimport free, malloc
41- from libc.string cimport memcmp
41+ from libc.string cimport memcmp, memcpy
4242
4343import warnings
4444
@@ -299,12 +299,10 @@ cdef class SpecializationConstant:
299299 integers, the first argument is interpreted as the number of bytes and
300300 the second argument is interpreted as a pointer to the data.
301301
302- Note that when constructing from a buffer, the
303- :class:`.SpecializationConstant`, shares memory with the original object.
304- Modifications to the original object's data after construction will be
305- reflected when the :class:`.SpecializationConstant` is used to create a
306- :class:`.SyclKernelBundle`. This is not the case when constructing from a
307- raw pointer, as the data is copied.
302+ Note that construction of the :class:`.SpecializationConstant` copies the
303+ input, so modifications made after construction of the
304+ :class:`.SpecializationConstant` will not be reflected in the
305+ :class:`.SyclKernelBundle`.
308306
309307 Args:
310308 spec_id (int):
@@ -320,11 +318,12 @@ cdef class SpecializationConstant:
320318 """
321319
322320 cdef _spec_const _spec_const
323- cdef Py_buffer _buffer
324321
325322 def __cinit__ (self , spec_id , *args ):
326323 cdef int ret_code = 0
327324 cdef object target_obj = None
325+ cdef Py_buffer _local_buffer
326+ cdef void * copied_data
328327
329328 if not isinstance (spec_id, numbers.Integral):
330329 raise TypeError (
@@ -349,16 +348,16 @@ cdef class SpecializationConstant:
349348 )
350349 elif isinstance (args[0 ], str ):
351350 target_obj = np.ascontiguousarray(args[1 ], dtype = args[0 ])
351+ else :
352+ raise TypeError (
353+ " Invalid arguments."
354+ )
352355
353356 elif len (args) == 1 :
354357 target_obj = args[0 ]
355358 if not PyObject_CheckBuffer(target_obj):
356359 # attempt to coerce to a numpy array
357360 target_obj = np.ascontiguousarray(target_obj)
358- else :
359- raise TypeError (
360- " Invalid arguments."
361- )
362361
363362 if isinstance (target_obj, np.ndarray):
364363 if target_obj.dtype.kind not in (" b" , " i" , " u" , " f" , " c" ):
@@ -373,17 +372,30 @@ cdef class SpecializationConstant:
373372 )
374373
375374 ret_code = PyObject_GetBuffer(
376- target_obj, & (self ._buffer ), PyBUF_SIMPLE | PyBUF_ANY_CONTIGUOUS
375+ target_obj, & (_local_buffer ), PyBUF_SIMPLE | PyBUF_ANY_CONTIGUOUS
377376 )
378377 if ret_code != 0 :
379378 raise ValueError (
380379 " Failed to get buffer view for the provided object."
381380 )
382- self ._spec_const.value = < void * > self ._buffer.buf
383- self ._spec_const.size = < size_t> self ._buffer.len
381+
382+ self ._spec_const.size = < size_t> _local_buffer.len
383+ copied_data = malloc(self ._spec_const.size)
384+
385+ if copied_data == NULL :
386+ PyBuffer_Release(& (_local_buffer))
387+ raise MemoryError (
388+ " Failed to allocate memory for specialization constant data."
389+ )
390+
391+ memcpy(copied_data, _local_buffer.buf, self ._spec_const.size)
392+ self ._spec_const.value = copied_data
393+
394+ PyBuffer_Release(& (_local_buffer))
384395
385396 def __dealloc__ (self ):
386- PyBuffer_Release(& (self ._buffer))
397+ if self ._spec_const.value != NULL :
398+ free(< void * > self ._spec_const.value)
387399
388400 def __repr__ (self ):
389401 return f" SpecializationConstant({self._spec_const.id})"
0 commit comments