Generating C++ Modules
The Command Shell
Pixels and Images
Graphics: plots, profiles
Image file I/O
Creating New Modules
The Command Shell
In command mode, or shell mode, you may type any C++ instruction "valid in the current environment" ... as there literally are hundreds of classes and thousands of methods and functions, there are lots of things to document.
Let's introduce some basic commands to explain the idea. The usual mathematical functions are defined, and you may define any new variable you like:
To simplify typing, you may omit the final semicolon on the line, and even the parentheses for one-argument function calls:
(You should not use these syntax shortcuts in script files).
Of course, this has nothing to do with imalab directly, so let's look at the global environment. The Global Environment contains a number of variables directly linked with the screen display. We list here some important variables, with their types (image types will be explained later).
Example: Clear Screen, modify movie parameters
First example: set delai to zero, clear screen, continue with sequence display.
Example: Inspect Pixels
We want to identify some interesting point in the image, and print pixel values around that point. The function call get-point(false) initiates a mouse-click on the screen; it then gives you the coordinates of the point you click on the screen. (These coordinates are relative to the image, you can click in any screen position).
You then use the function pixrect
Using the GetPixel method, you may also obtain a single pixel value directly:
There is a separate page on inspecting images and pixels.
help-classes() prints the list of currently known classes, i.e. the classes currently loaded in the system
help class prints the list of methods of the given class, not including methods inherited from parent classes.
a-propos string prints the list of all currently defined identifiers with the given string in their name.
help number gives information on the item with the given number, on the last list printed out by help or a-propos. This is the most frequent way to get information on methods and functions. Notice that the number always refers to the last list that has been printed!
Typical command sequence
A shell fundamentally is defined by two things: an environment and a language. The environment defines what names you may use to designate your objects of discourse. The language defines what you can do with your objects (semantics), and how you express this (syntax).
For example, with a Unix shell you mostly use filenames to designate commands and data files, and you can execute commands in various ways.
In the Ravi shell you are inside a program execution: names designate C++ objects of various types, in particular functions, class instances, structured data. A shell command is a C++ instruction, like a piece of a main program, that is executed immediately and incrementally.
Object semantics are very much like Java's: the shell only manipulates objects through "references", there is no pointer manipulation, objects are created via the operator new, and accessed with the operator. ... note the point here is the operator.
You should understand objects in the Ravi shell as handles composed of a pointer and a dynamic typecode.
When using the shell as interface to a C++ library, the shell accepts a shell-object-handle as an argument of pointer type, or reference type, and in some cases event as a plain object type. See 2 paragraphs below.
Differences with C++ Syntax
Even though the shell syntax looks very much like C++, you may use only a strict subset.
The restrictions/differences help to make the shell convenient for interactive and incremental programming.
Many differences are familiar to Java programmers:
There also are some restrictions because the shell interpreter is incomplete:
Compatibility with Scheme.
As a consequence of the above differences, the way you call a function or method in the shell may look erroneous to the C++ programmer! The best way to express this is to recommend you to obey to a certain discipline when defining your C++ prototypes.
Basically, the following two prototypes cannot be distinguished in the shell:
The code produced by the interface generator will accept the same shell object for both prototypes.
const qualifiers are ignored for prototype identification. This makes for a total of four prototypes which are different for the C++ compiler, but the same for the interface generator! In all cases, the call from the shell will have the form
where c is a handle for an instance of class C, as produced with
c = new C;
Morality: when your C++ source code uses overloading of this kind, you must be careful when generating the interface, guiding the generator with appropriate pragma declarations.
Link here to handle-with-new ... more problems.
My personal opinion: overloading with these types never is a good thing, and makes for errorprone code. In the shell, I want an abstract view of my code, I don't want to care for such fuss.
A fundamental property of the Imalab shell is extensibility: at any time, you may load new modules into the shell. A module puts new functions, classes, methods, objects into the shell. A strong point of the Ravi system is that modules can be generated automatically from header files, using dynamic libraries. This is the role of module generation. Module generation can become quite complex, so there is a long page on module generation.