{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": "## Writing a new Jupyter kernel" }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": "%mkdir cpp" }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": "Writing cpp/cpp_kernel.py" }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": "%%writefile cpp/cpp_kernel.py\n\nimport os\nimport os.path as op\nimport tempfile\n\n# We import the `getoutput()` function provided by IPython.\n# It allows us to do system calls from Python.\nfrom IPython.utils.process import getoutput\n\ndef exec_cpp(code):\n \"\"\"Compile, execute C++ code, and return the standard output.\"\"\"\n\n # We create a temporary directory. This directory will\n # be deleted at the end of the 'with' context.\n # All created files will be in this directory.\n with tempfile.TemporaryDirectory() as tmpdir:\n\n # We define the source and executable filenames.\n source_path = op.join(tmpdir, 'temp.cpp')\n program_path = op.join(tmpdir, 'temp')\n\n # We write the code to the C++ file.\n with open(source_path, 'w') as f:\n f.write(code)\n\n # We compile the C++ code into an executable.\n os.system(\"g++ {0:s} -o {1:s}\".format(\n source_path, program_path))\n\n # We execute the program and return the output.\n return getoutput(program_path)" }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": "Appending to cpp/cpp_kernel.py" }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": "%%writefile -a cpp/cpp_kernel.py\n\n\"\"\"C++ wrapper kernel.\"\"\"\nfrom ipykernel.kernelbase import Kernel\n\nclass CppKernel(Kernel):\n\n # Kernel information.\n implementation = 'C++'\n implementation_version = '1.0'\n language = 'c++'\n language_version = '1.0'\n language_info = {'name': 'c++',\n 'mimetype': 'text/plain'}\n banner = \"C++ kernel\"\n\n def do_execute(self, code, silent,\n store_history=True,\n user_expressions=None,\n allow_stdin=False):\n \"\"\"This function is called when a code cell is executed.\"\"\"\n\n if not silent:\n # We run the C++ code and get the output.\n output = exec_cpp(code)\n\n # We send back the result to the frontend.\n stream_content = {'name': 'stdout', 'text': output}\n self.send_response(self.iopub_socket, 'stream', stream_content)\n\n return {'status': 'ok',\n # The base class increments the execution count\n 'execution_count': self.execution_count,\n 'payload': [],\n 'user_expressions': {},\n }\n\nif __name__ == '__main__':\n from ipykernel.kernelapp import IPKernelApp\n IPKernelApp.launch_instance(kernel_class=CppKernel)" }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": "Writing cpp/kernel.json" }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": "%%writefile cpp/kernel.json\n{\n \"argv\": [\"python\",\n \"cpp/cpp_kernel.py\",\n \"-f\",\n \"{connection_file}\"\n ],\n \"display_name\": \"C++\"\n}" }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": "[InstallKernelSpec] Installed kernelspec cpp in /Users/cyrille/Library/Jupyter/kernels/cpp" }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": "!jupyter kernelspec install --replace --user cpp" }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": "Available kernels:\n cpp\n python3" }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": "!jupyter kernelspec list" } ], "metadata": {}, "nbformat": 4, "nbformat_minor": 0 }