Prima Homepage
Generating C++ Modules
User Manual
The Command Shell
Running Imalab
Plugin Process
Pixels and Images
Interactive selection
Graphics: plots, profiles
Image file I/O
Image display
Connectivity Analysis
Image Processing(1)
Gaussian operators
Technical Documentation
Creating New Modules
Tutorial Download


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.

Introduction: Simple Examples

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:

exp cos pow(x2,sq 2)
(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).

  • current-image Type: TBitmapABGR
  • sequence-width image width: number of columns
  • sequence-height image height: number of lines
  • ima-ix indexe of current-image
  • delai For continuous mode: delay between two images.
  • screen The X-window used for imalab display

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
pixrect(bmp,x0,y0,w,h,[ch]) to print pixel values to your terminal. The optional channel argument should be a value between 0 and 3.


Using the GetPixel method, you may also obtain a single pixel value directly:


There is a separate page on inspecting images and pixels.

help and a-propos

Basic functions:

help class
help subject
a-propos string

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

help-classes()   // lists classes
help 3  // lists methods of class number 3
help 7  // lists profiles of method number 7

Fundamental Concepts for Shell Programming

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.

  • No declarations. An assignment implicitly declares a new variable, if necessary.
  • The semi-colon at the end of a command is optional.
  • You may drop parentheses around the argument of a one argument function, e.g. write sin cos 3.1.
  • Special definitions, like the | operator for string concatenation.

Many differences are familiar to Java programmers:

  • Use . to access a class member function (not ->).
  • No * & : no indirection or reference operator
  • No pointer arithmetic.
  • No delete operator. Automatic garbage collection takes care of memory management.
  • No cast operators

There also are some restrictions because the shell interpreter is incomplete:

  • No allocation of vectors (e.g. s1=new char[20])
  • No access to non-function class members, i.e. you can access an object only through its methods.
  • There are (temporary) restrictions on the use of operators.

Compatibility with Scheme.

  • The minus sign is a normal character inside an identifier. The minus operator must be preceded by space, or by another operator,
    e.g. x -y*-2;

  • A special character may be included in an identifier by escaping it with the \-character
    e.g. exact-\>inexact(x);

  • A Scheme-list may be indexed with the operator[]
    e.g. list(1,2,3)[1] has value 2

Automatic dereferencing and indistinguishable prototypes

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:

  class C;
  void fn(C & arg);
  void fn(C * arg);

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.

Extending the shell

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.

Multi Language Shell