Bindings to Qt and WebEngine.
Common Lisp has a way to interact with C code via the so called CFFI (C Foreign Function Interface). This interface allows any C code to be called by Common Lisp. At this time, there is no universal foreign function interface for C++. This presents a problem when we wish to call Qt code (which is written in C++).
In order to circumvent this problem, we can write functions in C that call the C++ code that we need. Concretely it looks like this:
interface.h
we declare a function to wrap some C++ function we want to use.interface.cpp
we implement the C function declared ininterface.h
with the C++ code inside of it.interface.lisp
we implement a definition via CFFI so that Lisp code can call the function defined ininterface.cpp
In this way, we can now invoke C++ through Lisp. A concrete example is shown below for a single function:
extern "C" void widgetShow(void* widget);
void widgetShow(void* widget) {
QWidget *_widget = reinterpret_cast<QWidget*>(widget);
_widget->show();
}
(defcfun ("widgetShow" widget-show) :void
(widget :pointer))
(export 'widget-show)
The library requires Qt5 and Qt5 Webengine. More specifically, you don’t need all of Qt5, the following Qt5 components are enough:
- qtbase
- qtwebengine
- qtwebchannel
- qtdeclarative
make all
After compiling, you will need to copy the shared libraries to a location where CFFI can find them. If you need to append a location for CFFI, you can add the following lines to your Lisp initialization:
(ql:quickload :cffi)
(pushnew "/opt/local/lib/" cffi:*foreign-library-directories* :test #'equal)
The above demonstrates an example in SBCL, where the location of the
shared library will be in /opt/local/lib
.
(sb-int:with-float-traps-masked (:invalid :inexact :overflow) (cl-webengine::run))
(trivial-main-thread:call-in-main-thread
(lambda () (sb-int:with-float-traps-masked (:invalid :inexact :overflow) (cl-webengine::run))))