Prima Homepage
ImaLab
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
Tutorial Download

[PREV][SUIV]

Creating New Modules

Question: how can I add my own code, written in C++ or C, to the Imalab shell? Answer: you construct a Module with your code. A module can be loaded into the shell at any time, and your code be used in the same way as native Imalab code (function, objects, methods).

This page starts with a few introductory examples of module generation, to give a general idea of how this question is handled in the Ravi/Imalab system.

There is an enormous amount of technical problems related to module generation - these will be discussed piece by piece later on.

There is a separate page on details of Unix Commands for Module Creation.

Contents of this page

ravitool --generate: Command line parameters

The first step in module generation is automatic program generation using the command ravitool --generate. We document this command here in a place easy to find; skip on first reading.

General format as Unix command:

ravitool --generate options source_files

This is strictly equivalent to

ravi -mod r-ig options source_files

source-files either is a single .ph file, or a (possibly empty) list of header files. Options are the following:

  • -o name output file name
  • -project Imalab defines project settings
  • -u name use declaration file name
  • -I dir add dir to header-file search path
  • -D name define preprocessor symbol
  • -R dir add dir to module path
  • -r module require module
  • -i name additional include file
  • -ia interactive mode (for debugging)
  • -cpp-trace n n=0,1,2,4 detailed preprocessor trace (for debugging)
  • -nomsg completely silent mode
  • -cc name out of date

Preprocessor defaults: when the source file is a .ph file, the preprocessor is not active. When the source file(s) are header files, the preprocessor is active.

The preprocessor symbol RAVI_INTERFACE always is defined during module generation.

Introduction: Interfacing a C function

This example shows how to extend the shell - the Scheme interpreter - with functions written in C.

Globally our goal is the following. Our C-code is composed of a header file essai1.h and an implementation file essai1.cc. The code implements just one function: ilog2. The header file simply reads as follows:


int ilog2(int i);

We want to be able to use this function in the shell.

Step 1: Making the module: execute a series of Unix commands to create a new Imalab module called "modessai1".

Step2: the module is used inside Imalab.

Step 1 - Commands:

ravitool --generate -o modessai1.cc -i essai1.cc essai1.h
ravitool --compile -o modessai1.o modessai1.cc
ravitool --link -o modessai1.so modessai1.o

The first of these commands generates the file modessai1.cc which is then compiled and link-edited to produce the file modessai1.so. The commands are emitted via the command ravitool which in turn calls the C++ compiler with the appropriate options.

The result of this first step is the file modessai1.so which is a shared object file that can be dynamically loaded into the Ravi interpreter.

Step 2 - Loading and Use in the shell (C-syntax)In the Imalab shell, or the ravi shell, use the following commands in C++-syntax mode


ilog2          // this proves that ilog2 is not yet defined
load modessai1 // load is (non standard) Scheme function
ilog2         // now defined
ilog2(5341);  // can be used as you expect
ilog2("ab");  // type control

Step 2 - Use in the shell (Scheme-syntax)In Scheme mode, the commands of the preceding paragraph are written as follows:


ilog2          ; proves ilog2 not yet defined
(load "modessai1") ; load is (non standard) Scheme function
ilog2         ; now defined
(ilog2 5341)  ; can be used as you expect
(ilog2 "ab")  ; type control

Generated file

As can be seen in this example, the classical compile-link cycle is replaced here by a cycle generate-compile-link. It is useful to have some understanding of the generated file, to understand the difficulties to come.

Include source files

Generated function Sc_ilog2: argument check, argument conversion, function call, result conversion.

Initialization code, defines symbol ilog2 in the shell.


#include "essai1.h"
#include "essai1.cc"

static Ravi::Boolean localInitFunc(void); static ScInitFunc go(localInitFunc);

void Sc_ilog2() { ScVal * FB = & VS_ElemQ(- GetPar()); int num = 0; if(num = 0 , IsFixNum(FB[0])) { SetResult(ScFixNum(ilog2(GetFixVal(FB[0])))); return ; } Errorf("bad arg [pos %d] for function %s",num,"ilog2"); }

Ravi::Boolean localInitFunc() { MakePutCProc("ilog2",Sc_ilog2,1,ScNil); return true; }

What can be learnt from this example

The above procedure generate-compile-link-load works for C and C++ code, in the case where no particular difficulties arise. You can look at a few more examples to realize how powerful the method is.

Interfacing a library

We don't really need implementation code for module generation - we can do without the .cc files in the above examples.

Let's take the following example: I have a library $HOME/Soft/lib/libpyramid.so and the associated header files BinomialDogPyramid.h LaplacianPyramid.h DogPyramid.h in the directory $HOME/Soft/include.

Look carefully at the commands to generate such a module - they resemble closely the first example!


	ravitool --generate -project Imalab -I $HOME/Soft/include -o modpyramid.cc  \
		 BinomialDogPyramid.h LaplacianPyramid.h DogPyramid.h
	ravitool --compile -o modpyramid.o modpyramid.cc
	ravitool --link -L$HOME/Soft/lib -lpyramid -o modpyramid.so modpyramid.o

Comments: The ravitool --generate command has a parameter -project Imalab which specifies that the pyramid code uses data structures from the Imalab project; this introduces a large number of "declarations" that will be explained in the following paragraph on advanced topics. (Through the file Site-Module/Imalab/project.dcl).

For other libraries, of course, you will not need the -project Imalab parameter - but chances are that you need to give some special information that the interface generator cannot deduce frome the header files. This is a hairy subject to be explained in the next paragraph.

Advanced Topics

memory management

preprocessor commands

C++ syntax

templates

shell interface

miscellaneous information: names