@@ -407,6 +407,46 @@ class MyBool(ctypes.c_bool):
407407 assert holder .ptr != 0
408408
409409
410+ @requires_module (np , "2.1" )
411+ def test_launch_scalar_argument_ctypes_subclass_fallback ():
412+ """Subclassed ctypes scalars survive the launch path and reach the kernel correctly."""
413+
414+ class MyInt32 (ctypes .c_int32 ):
415+ pass
416+
417+ dev = Device ()
418+ dev .set_current ()
419+
420+ mr = LegacyPinnedMemoryResource ()
421+ b = mr .allocate (np .dtype (np .int32 ).itemsize )
422+ arr = np .from_dlpack (b ).view (np .int32 )
423+ arr [:] = 0
424+
425+ scalar = MyInt32 (- 123456 )
426+
427+ code = r"""
428+ template <typename T>
429+ __global__ void write_scalar(T* arr, T val) {
430+ arr[0] = val;
431+ }
432+ """
433+
434+ arch = "" .join (f"{ i } " for i in dev .compute_capability )
435+ pro_opts = ProgramOptions (std = "c++17" , arch = f"sm_{ arch } " )
436+ prog = Program (code , code_type = "c++" , options = pro_opts )
437+ ker_name = "write_scalar<signed int>"
438+ mod = prog .compile ("cubin" , name_expressions = (ker_name ,))
439+ ker = mod .get_kernel (ker_name )
440+
441+ # This exercises the prepare_ctypes_arg isinstance fallback through a real launch.
442+ stream = dev .default_stream
443+ config = LaunchConfig (grid = 1 , block = 1 )
444+ launch (stream , config , ker , arr .ctypes .data , scalar )
445+ stream .sync ()
446+
447+ assert arr [0 ] == scalar .value
448+
449+
410450def test_kernel_arg_numpy_subclass_isinstance_fallback ():
411451 """Subclassed numpy scalars hit the isinstance fallback in prepare_numpy_arg."""
412452 from cuda .core ._kernel_arg_handler import ParamHolder
@@ -421,6 +461,46 @@ class MyFloat32(np.float32):
421461 assert holder .ptr != 0
422462
423463
464+ @requires_module (np , "2.1" )
465+ def test_launch_scalar_argument_numpy_subclass_fallback ():
466+ """Subclassed numpy scalars survive the launch path and reach the kernel correctly."""
467+
468+ class MyFloat32 (np .float32 ):
469+ pass
470+
471+ dev = Device ()
472+ dev .set_current ()
473+
474+ mr = LegacyPinnedMemoryResource ()
475+ b = mr .allocate (np .dtype (np .float32 ).itemsize )
476+ arr = np .from_dlpack (b ).view (np .float32 )
477+ arr [:] = 0.0
478+
479+ scalar = MyFloat32 (3.14 )
480+
481+ code = r"""
482+ template <typename T>
483+ __global__ void write_scalar(T* arr, T val) {
484+ arr[0] = val;
485+ }
486+ """
487+
488+ arch = "" .join (f"{ i } " for i in dev .compute_capability )
489+ pro_opts = ProgramOptions (std = "c++17" , arch = f"sm_{ arch } " )
490+ prog = Program (code , code_type = "c++" , options = pro_opts )
491+ ker_name = "write_scalar<float>"
492+ mod = prog .compile ("cubin" , name_expressions = (ker_name ,))
493+ ker = mod .get_kernel (ker_name )
494+
495+ # This exercises the prepare_numpy_arg isinstance fallback through a real launch.
496+ stream = dev .default_stream
497+ config = LaunchConfig (grid = 1 , block = 1 )
498+ launch (stream , config , ker , arr .ctypes .data , scalar )
499+ stream .sync ()
500+
501+ assert arr [0 ] == scalar
502+
503+
424504def test_kernel_arg_python_isinstance_fallbacks ():
425505 """Subclassed Python builtins hit the isinstance fallback in ParamHolder."""
426506 from cuda .core ._kernel_arg_handler import ParamHolder
0 commit comments