C++/Xeus Cling Environment

This notebook describes and creates the default C++/Xeus Cling environment in Nextjournal. Check out the showcase if you want to see what the environment contains. To see how it’s built, see setup.

Showcase

Imported from the Xeus Cling example notebook.

Output and error streams

std::cout and std::cerr are redirected to the notebook frontend.

#include <iostream>
std::cout << "some output" << std::endl;
0.7s
in C++17
Xeus Cling
std::cerr << "some error" << std::endl;
0.5s
in C++17
Xeus Cling
#include <stdexcept>
0.0s
in C++17
Xeus Cling

Commented out, kills a run-all.

//throw std::runtime_error("Unknown exception");
0.0s
in C++17
Xeus Cling

Omitting the ; in the last statement of a cell results in an output being printed

int j = 5;
0.0s
in C++17
Xeus Cling
j
1.2s
in C++17
Xeus Cling
5

Interpreting the C++ programming language

cling has a broad support of the features of C++. You can define functions, classes, templates, etc ...

Functions

double sqr(double a)
{
    return a * a;
}
0.0s
in C++17
Xeus Cling
double a = 2.5;
double asqr = sqr(a);
asqr
0.8s
in C++17
Xeus Cling
6.2500000

Classes

class Foo
{
public:
    virtual ~Foo() {}
    
    virtual void print(double value) const
    {
        std::cout << "Foo value = " << value << std::endl;
    }
};
0.0s
in C++17
Xeus Cling
Foo bar;
bar.print(1.2);
0.8s
in C++17
Xeus Cling

Polymorphism

class Bar : public Foo
{
public:
    virtual ~Bar() {}
    
    virtual void print(double value) const
    {
        std::cout << "Bar value = " << 2 * value << std::endl;
    }
};
0.0s
in C++17
Xeus Cling
Foo* bar2 = new Bar;
bar2->print(1.2);
delete bar2;
0.5s
in C++17
Xeus Cling

Templates

#include <typeinfo>
template <class T>
class FooT
{
public:
    
    explicit FooT(const T& t) : m_t(t) {}
    
    void print() const
    {
        std::cout << typeid(T).name() << " m_t = " << m_t << std::endl;
    }
    
private:
    
    T m_t;
};
template <>
class FooT<int>
{
public:
    
    explicit FooT(const int& t) : m_t(t) {}
    
    void print() const
    {
        std::cout << "m_t = " << m_t << std::endl;
    }
    
private:
    
    int m_t;
};
0.0s
in C++17
Xeus Cling
FooT<double> foot1(1.2);
foot1.print();
0.6s
in C++17
Xeus Cling
FooT<int> foot2(4);
foot2.print();
0.6s
in C++17
Xeus Cling

C++11 / C++14 support

class Foo11
{
public:
    
    Foo11() { std::cout << "Foo11 default constructor" << std::endl; }
    Foo11(const Foo11&) { std::cout << "Foo11 copy constructor" << std::endl; }
    Foo11(Foo11&&) { std::cout << "Foo11 move constructor" << std::endl; }
};
0.0s
in C++17
Xeus Cling
Foo11 f1;
Foo11 f2(f1);
Foo11 f3(std::move(f1));
0.4s
in C++17
Xeus Cling
#include <vector>
std::vector<int> v = { 1, 2, 3};
auto iter = ++v.begin();
v
0.5s
in C++17
Xeus Cling
{ 1, 2, 3 }
*iter
0.4s
in C++17
Xeus Cling
2

... and also lambda, universal references, decltype, etc ...

Documentation and completion

  • Documentation for types of the standard library is retrieved on cppreference.com.

  • The quick-help feature can also be enabled for user-defined types and third-party libraries. More documentation on this feature is available at https://xeus-cling.readthedocs.io/en/latest/inline_help.html.

?std::vector
0.1s
in C++17
Xeus Cling

Using the display_data mechanism

For a user-defined type T, the rich rendering in the notebook and JupyterLab can be enabled by by implementing the function xeus::xjson mime_bundle_repr(const T& im), which returns the JSON mime bundle for that type.

More documentation on the rich display system of Jupyter and Xeus-cling is available at https://xeus-cling.readthedocs.io/en/latest/rich_display.html

Image example

#include <string>
#include <fstream>
#include "xtl/xbase64.hpp"
#include "xeus/xjson.hpp"
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;
    };
    
    xeus::xjson mime_bundle_repr(const image& i)
    {
        auto bundle = xeus::xjson::object();
        bundle["image/png"] = xtl::base64encode(i.m_buffer.str());
        return bundle;
    }
}
0.3s
in C++17
Xeus Cling
marie.png
im::image marie(NJ__REF_);
marie
0.7s
in C++17
Xeus Cling

Audio example

#include <string>
#include <fstream>
#include "xtl/xbase64.hpp"
#include "xeus/xjson.hpp"
namespace au
{
    struct audio
    {   
        inline audio(const std::string& filename)
        {
            std::ifstream fin(filename, std::ios::binary);   
            m_buffer << fin.rdbuf();
        }
        
        std::stringstream m_buffer;
    };
    
    xeus::xjson mime_bundle_repr(const audio& a)
    {
        auto bundle = xeus::xjson::object();
        bundle["text/html"] =
           std::string("<audio controls=\"controls\"><source src=\"data:audio/wav;base64,")
           + xtl::base64encode(a.m_buffer.str()) +
            "\" type=\"audio/wav\" /></audio>";
        return bundle;
    }
}
0.2s
in C++17
Xeus Cling
audio.wav
au::audio drums(NJ__REF_);
drums
0.8s
in C++17
Xeus Cling

Display

#include "xcpp/xdisplay.hpp"
0.0s
in C++17
Xeus Cling
xcpp::display(drums);
0.5s
in C++17
Xeus Cling

Update-display

#include <string>
#include "xcpp/xdisplay.hpp"
namespace ht
{
    struct html
    {   
        inline html(const std::string& content)
        {
            m_content = content;
        }
        std::string m_content;
    };
    xeus::xjson mime_bundle_repr(const html& a)
    {
        auto bundle = xeus::xjson::object();
        bundle["text/html"] = a.m_content;
        return bundle;
    }
}
// A blue rectangle
ht::html rect(R"(
<div style='
    width: 90px;
    height: 50px;
    line-height: 50px;
    background-color: blue;
    color: white;
    text-align: center;'>
Original
</div>)");
0.4s
in C++17
Xeus Cling
xcpp::display(rect, "some_display_id");
0.4s
in C++17
Xeus Cling
Original
// Update the rectangle to be red
rect.m_content = R"(
<div style='
    width: 90px;
    height: 50px;
    line-height: 50px;
    background-color: red;
    color: white;
    text-align: center;'>
Updated
</div>)";
xcpp::display(rect, "some_display_id", true);
0.5s
in C++17
Xeus Cling

Clear output

#include <chrono>
#include <iostream>
#include <thread>
#include "xcpp/xdisplay.hpp"
0.1s
in C++17
Xeus Cling
std::cout << "hello" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
xcpp::clear_output();  // will flicker when replacing "hello" with "goodbye"
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "goodbye" << std::endl;
2.5s
in C++17
Xeus Cling
std::cout << "hello" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
xcpp::clear_output(true);  // prevents flickering
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "goodbye" << std::endl;
2.3s
in C++17
Xeus Cling

Magics

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

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

More documentation for magics is available at https://xeus-cling.readthedocs.io/en/latest/magics.html.

#include <algorithm>
#include <vector>
0.0s
in C++17
Xeus Cling
std::vector<double> to_shuffle = {1, 2, 3, 4};
0.1s
in C++17
Xeus Cling

Commented out, doesn't work.

// %timeit std::random_shuffle(to_shuffle.begin(), to_shuffle.end());
0.0s
in C++17
Xeus Cling

XTensor

  • GitHub repository: https://github.com/QuantStack/xtensor/

  • Online documentation: https://xtensor.readthedocs.io/

  • NumPy to xtensor cheat sheet: http://xtensor.readthedocs.io/en/latest/numpy.html

xtensor is a C++ library for manipulating N-D arrays with an API very similar to that of numpy.

#include <iostream>
#include "xtensor/xarray.hpp"
#include "xtensor/xio.hpp"
#include "xtensor/xview.hpp"
xt::xarray<double> arr1
  {{1.0, 2.0, 3.0},
   {2.0, 5.0, 7.0},
   {2.0, 5.0, 7.0}};
xt::xarray<double> arr2
  {5.0, 6.0, 7.0};
xt::view(arr1, 1) + arr2
2.3s
in C++17
Xeus Cling
  7.
 11.
 14.

Together with the C++ Jupyter kernel, xtensor offers a similar experience as NumPy in the Python Jupyter kernel, including broadcasting and universal functions.

#include <iostream>
#include "xtensor/xarray.hpp"
#include "xtensor/xio.hpp"
0.0s
in C++17
Xeus Cling
xt::xarray<int> arr
  {1, 2, 3, 4, 5, 6, 7, 8, 9};
arr.reshape({3, 3});
std::cout << arr;
1.3s
in C++17
Xeus Cling
#include "xtensor-blas/xlinalg.hpp"
1.9s
in C++17
Xeus Cling
xt::xtensor<double, 2> m = {{1.5, 0.5}, {0.7, 1.0}};
std::cout << "Matrix rank: " << std::endl << xt::linalg::matrix_rank(m) << std::endl;
std::cout << "Matrix inverse: " << std::endl << xt::linalg::inv(m) << std::endl;
std::cout << "Eigen values: " << std::endl << xt::linalg::eigvals(m) << std::endl;
2.1s
in C++17
Xeus Cling
xt::xarray<double> arg1 = xt::arange<double>(9);
xt::xarray<double> arg2 = xt::arange<double>(18);
arg1.reshape({3, 3});
arg2.reshape({2, 3, 3});
std::cout << xt::linalg::dot(arg1, arg2) << std::endl;
1.8s
in C++17
Xeus Cling

Setup

Install

The Xeus Cling Homepage really wants us to install this via conda, so we'll base off the Minimal Python 3 environment. Make sure the default channels take priority—we want as little as possible from the conda-forge channel, to ensure smooth operation. May as well also install xtensor and its add-ons.

conda install -c defaults -c conda-forge \
  xeus-cling cling xtensor xtensor-blas xtensor-io \
  jupyter
conda clean -qtipy
ldconfig
196.7s
Xeus Cling (Bash)

Upgrade Jupyter components. Using dev on jupyter-core to address an issue with connection file permissions, remove when v4.6.2 comes out. —MPD, 17 Dec 2019.

pip install --upgrade jupyter-client \
  git+https://github.com/jupyter/jupyter_core
4.1s
Xeus Cling (Bash)

Check.

du -hsx /
python -V
conda -V
jupyter kernelspec list
4.6s
Xeus Cling (Bash)

Test Kernel

int x = 1
0.0s
C++17
Xeus Cling
x + 1
0.5s
C++17
Xeus Cling
2

Appendix

DIR=share/jupyter/kernels/
[ -d ~/.ipython/kernels ] && find ~/.ipython/kernels -name kernel.json || true
[ -d ~/.local/${DIR} ] && find ~/.local/${DIR} -name kernel.json || true
[ -d /usr/${DIR} ] && find /usr/${DIR} -name kernel.json || true
[ -d /usr/local/${DIR} ] && find /usr/local/${DIR} -name kernel.json || true
[ -d /opt/conda/${DIR} ] && find /opt/conda/${DIR} -name kernel.json || true
0.9s
Bash Tests (Bash)
Xeus Cling
find / -name kernel.json
3.3s
Bash Tests (Bash)
Xeus Cling

This command starts the kernel, this is not meant to be run other than for debugging purposes

/opt/conda/bin/xcpp -f /connection_file.json -std=c++17
Bash Tests (Bash)
Xeus Cling
{
  "stdin_port": 57557, 
  "ip": "127.0.0.1", 
  "control_port": 49615, 
  "hb_port": 42540, 
  "signature_scheme": "hmac-sha256", 
  "key": "", 
  "kernel_name": "", 
  "shell_port": 57555, 
  "transport": "tcp", 
  "iopub_port": 57556
}
connection_file.json
JSON
Runtimes (3)
Runtime Languages (1)