* Insert lame excuse about delay here (Shame on me) *
Nowadays, Scilab’s compilation generates 2 executables: scilab-bin, the full-featured Java GUI interface (with Scinotes, Xcos and help browser tools); and scilab-cli-bin, which opens the shell on a simple terminal, and can even be made to run without Java dependencies, by disabling some features.
From a developer’s point of view, that means that Scilab’s codebase already has the groundwork for handling different interfaces, allowing the definition of independent functions for text input and output, while the rest of processing code remains pretty much the same.
As we plan to integrate the Jupyter Kernel/Console/Notebook functionality into Scilab, first of all, read/write functions that implement the Wire Protocol communication must be provided and set according to the defined interface:
Even with that kind of facilitators, making my Jupyter messaging work part of Scilab is not such an easy task: as I looked for the components that the kernel logic needs to interoperate with, in order to build a complete implementation, a miriad of files and folders, yet to be fully understood, has shown itself.
Gladly, the directory structure related to this work is not that deep, and it was relatively easy to locate the C and C++ header/source files as they were referenced in the code I was inspecting.
Basically, each component used to build the entire Scilab application has its sources grouped in its own subfolder of the “modules” folder, at the root of Scilab’s source code, and it is firstly compiled to a library, before being linked to the main executable.
(As you can see, I already created a module folder for the Jupyter kernel code)
The startup module contains the starting point for the application (the main function, named “scilab.cpp”), which parses the command-line options, defines the used input/output methods and calls the [almost self explanatory] higher level Scilab engine initialization functions from the core module:
From InitScilab.h
Even if we could add the Jupyter kernel initialization logic to “scilab.cpp” through preprocessor directives (a.k.a. “#ifdef”s), Clément, my mentor, suggested that I created a separate main for it, inside the same startup directory, copying only what is needed, without all the JVM and OpenMPI handling, from the original one.
From jupyter_scilab_kernel.cpp
As we can’t run the connection update loop inside the main function anymore, and wouldn’t want to block execution of other tasks during message receiving/sending as well, the Jupyter kernel, now added as a new class, starts a separate connection thread on its static initializer, to handle the input (commands) and output (results) queue asynchronously.
From JupyterKernel.hxx
To effectively make our new module work as a internal library, we mimic the way other modules work, exporting symbols for wrapper C-style functions that call kernel class methods:
From dynlib_jupyter.h
From InitializeJupyter.h
From JupyterMessagePrint.h
From JupyterMessageRead.h
With the code implemented so far, we should be able to handle simple “{execute,kernel_info,connect,shutdown}_request” calls properly. What remains to be done, regarding message handling, are command history and code completion/completeness/introspection, for which the needed Scilab functions are still being discovered.
But before that, I pretend to add my new sources to the [apparently complicated] build process, with Clément’s guidance, it seems, based on the makefiles he helpfully provided me.