C++ or C Gotchas

Advices and Gotchas when using cling and jupyter

The cling and xeus docs are good, but some informations are missing : this notebook adds more details.

Cling official docs: https://root.cern.ch/cling

.x filename.cxx - loads filename and calls void filename() if defined
.L library | filename.cxx - loads library or filename.cxx
.printAST - shows the abstract syntax tree after each processed entity
.I path - adds an include path

xeus-cling official docs: https://xeus-cling.readthedocs.io/en/latest/index.html

Some gotchas with cling and jupyter

Do not define two functions in the same cell or a global variable with another function

Failure example

this cell will give an error : "function definition is not allowed here"

int foo() { return 42; }
int foo2() {return 43; }
input_line_7:3:13: error: function definition is not allowed here
 int foo2() {return 43; }
            ^



Interpreter Error:

Correction

Create two cells

int foo() { return 42; }
int foo2() {return 43; }

Add using namespace std

If you try to display a std::string or a std::vector you might get some errors like this inside cling, when you are on the console (not inside notebook)

error: no template named 'basic_string'; did you mean 'std::basic_string'? You can solve this by adding a line using namespace std

Scanf does not work

scanf does not work properly. To make it work, we could write a wrapper around vsscanf. You could provide this code on top of the assignment as a read only code block for students. This should behave exactly like scanf but it uses std::cin internally .

#include <stdlib.h>
#include<stdarg.h>
#include <iostream>

int scanf_lab(const char * str, ...)
{
    std::string input_string;
    std::getline(std::cin, input_string);
    va_list args;
    va_start(args, str);
    int ret = vsscanf(input_string.c_str(), str, args );
    va_end(args);
    return ret;
}

int n;
scanf_lab("%d", &n);
11
n
11

Some more advices / missing docs

Add include path / And library path / load libraries

Add library and include path

#pragma cling add_library_path("...") will add a path to the library path
#pragma cling add_include_path("...") will add a path to the include path

Load libraries

#pragma cling load("mylibrary") will load a library. You do not need to add the library extension (.so, '.lib, or .dylib). You can also load a library using .L.

No semicolon in single line statements

Do not put a ";" at the end if you want to see the computation result The cell below will output a result:

2 * 3
6
2 * 3;

This is C++ : everything can be defined only once

If you run twice a code that defines the same variable or a function, you will encounter a compiler error, with a bad looking Red Error Message (error: redefinition of '...'). There are several ways to work around this but the easiest way is to select "Kernel/Restart" and re-run the different cells

Compiling header files and shared object files

Lets have a file a.cpp with some functions in the /root directory

int ret0 () {
   return 0;
}

int ret1() {
        return 1;
}

Lets have a file a.h with some functions in the /root directory

int ret0 ();
int ret1();

To compile shared object files, you have to install clang-9 and change paths.

apt install clang-9
export PATH=/usr/lib/llvm-9/bin/clang++:$PATH
clang++ -shared  a.cpp -o a.so
Now, in the notebook, we can do
.L /root/a.so

#pragma cling add_include_path("/root/")
#include <a.h>
ret1()
1
ret0()
0