xeus-cling

xeus-cling is a Jupyter kernel for C++ based on the C++ interpreter cling and the native implementation of the Jupyter protocol xeus.

Introduction

Licensing

We use a shared copyright model that enables all contributors to maintain the copyright on their contributions.

This software is licensed under the BSD-3-Clause license. See the LICENSE file for details.

Installation

_images/conda.svg

Using the conda-forge package

A package for xeus-cling is available for the mamba (or conda) package manager.

mamba install -c conda-forge xeus-cling
_images/cmake.svg

From source with cmake

You can also install xeus-cling from source with cmake. This requires that you have all the dependencies installed in the same prefix.

mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=/path/to/prefix ..
make install

On Windows platforms, from the source directory:

mkdir build
cd build
cmake -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX=/path/to/prefix ..
nmake
nmake install

Installing the Kernel Spec

When installing xeus-cling in a given installation prefix, the corresponding Jupyter kernelspecs are installed in the same environment and are automatically picked up by Jupyter if it is installed in the same prefix.

However, if Jupyter is installed in a different location, it will not pick up the new kernels. The xeus-cling kernels (for C++11, C++14 and C++17 respectively) can be registered with the following commands:

jupyter kernelspec install PREFIX/share/jupyter/xcpp11 --sys-prefix
jupyter kernelspec install PREFIX/share/jupyter/xcpp14 --sys-prefix
jupyter kernelspec install PREFIX/share/jupyter/xcpp17 --sys-prefix

For more information on the jupyter kernelspec command, please consult the jupyter_client documentation.

Build options

Build flags

You can specify additional build flags that will be used by xeus-cling to compile the code in the notebook. To do so, you need to edit the kernelspec file (usually share/jupyter/kernels/xcppSTD/kernel.json, where STD is the version of the cpp standard) and add the build flags in the argv array.

For instance, if you want to pass the -pthread -lpthread flags to xeus-cling and compile C++17 code, the C++17 kernelpec file becomes:

{
    "display_name": "C++17",
    "argv": [
        "/home/yoyo/miniconda3/envs/xwidgets/bin/xcpp",
        "-f",
        "{connection_file}",
        "-std=c++17",
        "-pthread",
        "lpthread"
    ],
    "language": "C++17"
}

Using third-party libraries

When building a binary, you usually specify the include directories and the library path of third-party libraries in the build tool. The library will be loaded upon binary execution.

xeus-cling is slightly different, it allows you to specify both include directories and library path, however you need to load the library explicitly. This is done with special pragma commands that you can use in a code cell in a Jupyter Notebook:

  • #pragma cling add_include_path("inc_directory")

  • #pragma cling add_library_path("lib_directory")

  • #pragma cling load("libname")

Magic commands

Magics are special commands for the kernel that are not part of the C++ programming language.

There are defined with the symbol % for a line magic and %% for a cell magic.

A few magics are available in xeus-cling. In the future, user-defined magics will also be enabled.

%%executable

Dump the code from all entered cells into an executable binary. The content of the cell is used for the body of the main function.

%%executable filename [-- linker options]
  • Example

_images/executable.png
  • Optional arguments:

You can use the following options which will be passed to the linker and will influence code generation:

-fsanitize

enable instrumentation with ThreadSanitizer

-g

enable debug information in the executable

%%file

This magic command copies the content of the cell in a file named filename.

%%file [-a] filename
  • Example

_images/file_magic.png
  • Optional argument:

-a

append the content to the file.

%timeit

Measure the execution time execution for a line statement (%timeit) or for a block of statements (%%timeit)

  • Usage in line mode

%timeit [-n<N> -r<R> -p<P>] statement
  • Usage in cell mode

%%timeit [-n<N> -r<R> -p<P>]
statements
  • Example

_images/timeit_magic.png
  • Optional arguments:

-n

execute the given statement <N> times in a loop. If this value is not given, a fitting value is chosen.

-r

repeat the loop iteration <R> times and take the best result. Default: 7

-p

use a precision of <P> digits to display the timing result. Default: 3

Displaying rich content

The Jupyter rich display system allows displaying rich content in the Jupyter notebook and other frontend.

This is achieved by sending mime bundles to the front-end containing various representations of the data that the frontend may use.

A mime bundle may contain multiple alternative representations of the same object for example

  • a text/html representation for the notebook and other web frontends.

  • a text/plain representation for the console.

Besides plain text and html, other mime type can be used such as image/png or even custom mime type for which a renderer is available in the front-end.

Default plain text representation

By default, xeus-cling provides a plain text representation for any object.

In the case of a basic type such as double or int, the value will be displayed.

For sequences (exposing an iterator pair begin / end), the content of the sequence is also displayed.

Finally, for more conplex types, the address of the object is displayed.

Providing custom mime representations for user-defined types

For a user-defined class myns::foo, you can easily provide a mime representation taylored to your needs such as a styled html table including the values of various attributes.

This can be achieved by simply overloading the function

nl::json mime_bundle_repr(const foo&);

in the same namespace myns as foo.

The rich display mechanism of xeus-cling will pick up this function through argument-dependent-lookup (ADL) and make use of it upon display.

Example: image/png representation of an image class

In this example, the im::image class holds a buffer read from a file. The mime_bundle_repr overload defined in the same namespace simply forwards the buffer to the frontend.

#include <string>
#include <fstream>

#include "xtl/xbase64.hpp"
#include "nlohmann/json.hpp"

namespace nl = nlohmann;

namespace im
{
    struct image
    {
        inline image(const std::string& filename)
        {
            std::ifstream fin(filename, std::ios::binary);
            m_buffer << fin.rdbuf();
        }

        std::stringstream m_buffer;
    };

    nl::json mime_bundle_repr(const image& i)
    {
        auto bundle = nl::json::object();
        bundle["image/png"] = xtl::base64encode(i.m_buffer.str());
        return bundle;
    }
}
_images/image.png

Displaying content in the frontend

The first way to display an object in the front-end is to omit the last semicolon of a code cell. When doing so, the last expression will be displayed.

Another way of achieving this, is to include the xcpp::display function and passing the object to display. xcpp::display is defined in the <xcpp/xdisplay.hpp> header.

_images/display.png

Note

A subtle distinction between using xcpp::display and omitting the last semicolon is that the latter results in a cell output including a prompt number, while the former will only show the rich front-end representation.

This behavior is consistent to the Python kernel implementation where 1 results in an output while print(1) result in a display message.

Inline documentation

The standard library

The xeus-cling kernel allows users to access help on functions and classes of the standard library.

In a code cell, typing ?std::vector will simply display the help page on vector from the cppreference website.

_images/help.png

Enabling the quick-help feature for third-party libraries

The quick help feature can be enabled for other libraries. To do so, a doxygen tag file for your library must be placed under the xeus-cling “data” directory of the installation prefix, namely

PREFIX/share/xeus-cling/tagfiles

For xeus-cling to be able to make use of that information, a JSON configuration file must be placed under the xeus-cling configuration directory of the installation prefix, namely

PREFIX/etc/xeus-cling/tags.d

Note

For more information on how to generate tag files for a doxygen documentation, check the relevant section of the doxygen documentation.

The format for the JSON configuration file is the following

{
    "url": "Base URL for the documentation",
    "tagfile": "Name of the doxygen tagfile"
}

For example the JSON configuration file for the documentation of the standard library is

{
    "url": "https://en.cppreference.com/w/",
    "tagfile": "cppreference-doxygen-web.tag.xml"
}

Note

We recommend that you only use the https protocol for the URL. Indeed, when the notebook is served over https, content from unsecure sources will not be rendered.

The case of breathe and sphinx documentation

Another popular documentation system is the combination of doxygen and sphinx, thanks for the breathe package, which generates sphinx documentation using the XML output of doxygen.

The xhale Python package can be used to convert the sphinx inventory files produced breathe into doxygen tag files.

_images/xtensor.png