Creating a Ravi Module

This page starts with a few examples to introduce the problem of module generation, and to show the spirit of the solution in the Ravi system. There is an enormous amount of technical problems related to module generation - these are handled piece by piece.

Introductory Examples

Command line parameters

Command line is one of the following

ravitool --generate options source_files

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
  • -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
  • -u name use declaration file name
  • -ia interactive mode (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 The code implements just one function: ilog2. We want to be able to use this function in the shell.

Header file

int ilog2(int i);


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

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

Use in the shell (C-syntax)The file is a shared object file which can be dynamically loaded into the Ravi interpreter:

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

Use in the shell (Scheme-syntax)

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 ilo2 in the shell.

#include "essai1.h"
#include ""

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-loadworks 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

Now let's come to the difficulties.

memory management

preprocessor commands

C++ syntax


shell interface

miscellaneous information: names