code: def capture_kernel_call(
      kernel, output_file, queue, g_size, l_size, *args, **kwargs
  ):
      try:
          source = kernel._source
      except AttributeError:
          raise RuntimeError(
              "cannot capture call, kernel source not available"
          )
  
      if source is None:
          raise RuntimeError(
              "cannot capture call, kernel source not available"
          )
  
      cg = PythonCodeGenerator()
  
      cg("# generated by pyopencl.capture_call")
      cg("")
      cg("import numpy as np")
      cg("import pyopencl as cl")
      cg("from base64 import b64decode")
      cg("from zlib import decompress")
      cg("mf = cl.mem_flags")
      cg("")
  
      cg('CODE = r"""//CL//')
      for line in source.split("\n"):
          cg(line)
      cg('"""')
  
      # {{{ invocation
  
      arg_data = []
  
      cg("")
      cg("")
      cg("def main():")
      with Indentation(cg):
          cg("ctx = cl.create_some_context()")
          cg("queue = cl.CommandQueue(ctx)")
          cg("")
  
          kernel_args = []
  
          for i, arg in enumerate(args):
              if isinstance(arg, cl.Buffer):
                  buf = bytearray(arg.size)
                  cl.enqueue_copy(queue, buf, arg)
                  arg_data.append(("arg%d_data" % i, buf))
                  cg(
                      "arg%d = cl.Buffer(ctx, "
                      "mf.READ_WRITE | cl.mem_flags.COPY_HOST_PTR," % i
                  )
                  cg(
                      "    hostbuf=decompress(b64decode(arg%d_data)))"
                      % i
                  )
                  kernel_args.append("arg%d" % i)
              elif isinstance(arg, (int, float)):
                  kernel_args.append(repr(arg))
              elif isinstance(arg, np.integer):
                  kernel_args.append(
                      "np.{}({})".format(
                          arg.dtype.type.__name__, repr(int(arg))
                      )
                  )
              elif isinstance(arg, np.floating):
                  kernel_args.append(
                      "np.{}({})".format(
                          arg.dtype.type.__name__, repr(float(arg))
                      )
                  )
              elif isinstance(arg, np.complexfloating):
                  kernel_args.append(
                      "np.{}({})".format(
                          arg.dtype.type.__name__, repr(complex(arg))
                      )
                  )
              else:
                  try:
                      arg_buf = memoryview(arg)
                  except Exception:
                      raise RuntimeError(
                          "cannot capture: "
                          "unsupported arg nr %d (0-based)" % i
                      )
  
                  arg_data.append(("arg%d_data" % i, arg_buf))
                  kernel_args.append(
                      "decompress(b64decode(arg%d_data))" % i
                  )
  
          cg("")
  
          g_times_l = kwargs.get("g_times_l", False)
          if g_times_l:
              dim = max(len(g_size), len(l_size))
              l_size = l_size + (1,) * (dim - len(l_size))
              g_size = g_size + (1,) * (dim - len(g_size))
              g_size = tuple(gs * ls for gs, ls in zip(g_size, l_size))
  
          global_offset = kwargs.get("global_offset", None)
          if global_offset is not None:
              kernel_args.append(
                  "global_offset=%s" % repr(global_offset)
              )
  
          cg("prg = cl.Program(ctx, CODE).build()")
          cg("knl = prg.%s" % kernel.function_name)
          if hasattr(kernel, "_scalar_arg_dtypes"):
  
              def strify_dtype(d):
                  if d is None:
                      return "None"
  
                  d = np.dtype(d)
                  s = repr(d)
                  if s.startswith("dtype"):
                      s = "np." + s
  
                  return s
  
              cg(
                  "knl.set_scalar_arg_dtypes((%s,))"
                  % ", ".join(
                      strify_dtype(dt)
                      for dt in kernel._scalar_arg_dtypes
                  )
              )
  
          cg("knl(queue, {}, {},".format(repr(g_size), repr(l_size)))
          cg("    %s)" % ", ".join(kernel_args))
          cg("")
          cg("queue.finish()")
  
      # }}}
  
      # {{{ data
  
      from zlib import compress
      from base64 import b64encode
  
      cg("")
      line_len = 70
  
      for name, val in arg_data:
          cg("%s = (" % name)
          with Indentation(cg):
              val = b64encode(compress(memoryview(val))).decode()
              i = 0
              while i < len(val):
                  cg(repr(val[i : i + line_len]))
                  i += line_len
  
              cg(")")
  
      # }}}
  
      # {{{ file trailer
  
      cg("")
      cg('if __name__ == "__main__":')
      with Indentation(cg):
          cg("main()")
      cg("")
  
      cg("# vim: filetype=pyopencl")
  
      # }}}
  
      if isinstance(output_file, str):
          with open(output_file, "w") as outf:
              outf.write(cg.get())
      else:
          output_file.write(cg.get())
  
label_desc: Use image node_id 1 for calling a global function with example usage: capture_kernel_call(kernel, output_file, queue, g_size, l_size) and returns: s, str