view c_kernel/ @ 9:101e99452042

Dockerized project :)
author Brendan Rius <>
date Sat, 26 Mar 2016 14:54:39 +0000
parents aa54c85303b6
line wrap: on
line source

from ipykernel.kernelbase import Kernel
import subprocess
import tempfile
import os

class CKernel(Kernel):
    implementation = 'c_kernel'
    implementation_version = '1.0'
    language = 'c'
    language_version = 'C11'
    language_info = {'name': 'c',
                     'mimetype': 'text/plain',
                     'file_extension': 'c'}
    banner = "C kernel.\n" \
             "Uses gcc, compiles in C11, and creates source code files and executables in temporary folder.\n"

    def __init__(self, *args, **kwargs):
        super(CKernel, self).__init__(*args, **kwargs)
        self.files = []

    def cleanup_files(self):
        """Remove all the temporary files created by the kernel"""
        for file in self.files:

    def new_temp_file(self, **kwargs):
        """Create a new temp file to be deleted when the kernel shuts down"""
        # We don't want the file to be deleted when closed, but only when the kernel stops
        kwargs['delete'] = False
        kwargs['mode'] = 'w'
        file = tempfile.NamedTemporaryFile(**kwargs)
        return file

    def execute_command(cmd):
        """Execute a command and returns the return code, stdout and stderr"""
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = p.communicate()
        return p.returncode, stdout.decode('utf-8'), stderr.decode('utf-8')

    def compile_with_gcc(source_filename, binary_filename):
        args = ['gcc', source_filename, '-std=c11', '-o', binary_filename]
        return CKernel.execute_command(args)

    def do_execute(self, code, silent, store_history=True,
                   user_expressions=None, allow_stdin=False):

        retcode, stdout, stderr = None, '', ''
        with self.new_temp_file(suffix='.c') as source_file:
            with self.new_temp_file(suffix='.out') as binary_file:
                retcode, stdout, stderr = self.compile_with_gcc(,
                if retcode != 0:
                    stderr += "[C kernel] GCC exited with code {}, the executable will not be executed".format(retcode)
      "GCC return code: {}".format(retcode))
      "GCC stdout: {}".format(stdout))
      "GCC stderr: {}".format(stderr))

        if retcode == 0:  # If the compilation succeeded
            retcode, out, err = CKernel.execute_command([])
            if retcode != 0:
                stderr += "[C kernel] Executable exited with code {}".format(retcode)
  "Executable retcode: {}".format(retcode))
  "Executable stdout: {}".format(out))
  "Executable stderr: {}".format(err))
            stdout += out
            stderr += err
  'Compilation failed, the program will not be executed')

        if not silent:
            stream_content = {'name': 'stderr', 'text': stderr}
            self.send_response(self.iopub_socket, 'stream', stream_content)
            stream_content = {'name': 'stdout', 'text': stdout}
            self.send_response(self.iopub_socket, 'stream', stream_content)
        return {'status': 'ok', 'execution_count': self.execution_count, 'payload': [], 'user_expressions': {}}

    def do_shutdown(self, restart):
        """Cleanup the created source code files and executables when shutting down the kernel"""