Skip to content

herrgahr/qling

Repository files navigation

Qling, the Qt interface for cling

This is a simple Qt interface for cling, the llvm-based C++ interpreter

It is at an early stage and definitely needs some love.

Compiling

First you need to install llvm, clang and cling from SVN. Follow the instructions at http://root.cern.ch/drupal/content/cling-build-instructions

Install it to some folder, either system wide or somewhere in your home (speficy via the --prefix option to llvm's configure-script).

Enter qling's subdirectory "qt-hack" and compile qatomic_sun.s (see Notes for explanation):

$ cd qt-hack
$ as qatomic_sun.s -o qatomic_sun.o
$ cd ..

After you've done this:

$ export LLVM_INSTALL=/dir/that/you/specified/as/llvm/install/prefix
$ qmake
$ make

and

$ ./qling

to start

Usage

Qling's main window consists of a text area that displays the code entered so far, a line edit for entering code line by line and a console-output. Enter the following example snippets at the line edit line by line: TODO: explain the differences between a .cpp file and the interpreter prompt...

Hello, world!

#include <iostream>
std::cout<<"Hello, world!"<<std::endl;

Interact with qling itself

qling's main window is made available to the interpreter as the global "MainWindow& qling". Of course MainWindow inherits QWidget. So the simplest example is closing qling:

qling.close();

Create a simple widget

QWidget w;
w.show();
w.setWindowTitle("Hello, interpreted C++ World");

Create a dock-widget in qling's main window

#include <QLabel>
#include <QDockWidget>
QLabel* label=new QLabel("TestDock-content");
QDockWidget* dynDock=new QDockWidget;
dynDock->setWidget(label);
dynDock->setWindowTitle("DynDock");
qling.addDockWidget(Qt::RightDockWidgetArea,dynDock);
//your qling window should now have an additional dock
//let's undock it:
dynDock->setFloating(true);
//and dock it again:
dynDock->setFloating(false);

Multi-line input

In multi-line mode, you can comfortably enter longer chunks of code and submit it in one go. If multi-line mode is active, the key actions to move in the history and submit code are only triggered when Ctrl is held. so Ctrl+KeyUp and Ctrl+KeyDown move in history, Ctrl+Enter submits code. So you can do stuff like this more naturally:

#include <QPushButton>
#include <QVBoxLayout>
QWidget* w=new QWidget;
QVBoxLayout* l=new QVBoxLayout(w);
QPushButton* b=new QPushButton("close");
l->addWidget(b);
QObject::connect(b,SIGNAL(clicked()),w,SLOT(close()));
w->setMinimumSize(300,300);
w->show();

...hit Ctrl+Enter and happlily look at your new widget... To make the window pop back up after you close it by pushing the button, we can use this (nonsical) hack: Instantiate a QObject-subclass with a timerEvent that calls w->show() every 1000msec.

#include <QTimerEvent>
struct T:public QObject{
T():m_timerId(startTimer(1000)){}
int m_timerId;
void timerEvent(QTimerEvent* e){
if(e->timerId()!=m_timerId)return;
w->show();
}
} timerInstance;

...and hit Ctrl+Enter again.

Notes

Inline assembly and the JIT

At the moment, llvm's JIT does not support inline assembler, which is needed for Qt's atomic stuff. For this reason there is a folder qt-hack, which includes modified qatomic-headers that #ifdef the inline asm away and cause the compiler to use the non-inline functions provided by qatomic_sun.s instead. These inline-asm issues likely cause other libraries that you might want to use from within cling to make the app crash, as well. An example is Eigen3 - I do have a patched version of Eigen3, too but there is a more elegant way to go: Recently the "MC framework" has been included in llvm and MC's JIT does support inline assembly. Unfortunately cling needs to be patched to make use of that and I have not yet been successful in making this work correctly - it segfaults atm which seems to be some JIT-memory-manager issue that I have yet to figure out. I have only spent ~1hour on this and then given up due to lack of time.

Credits

The core part of this program's functionality is provided by cling, which is developed at CERN. A big "thank you" goes out to Axel Naumann and Vassil Vassilev who've been providing me with help, tipps and support.

Have fun!