previous page next page reference home emBASIC home page

17 Extending and embedding

It is quite easy to add new built-in modules to emBASIC, if you know how to program in C. Such extension modules can do two things that can't be done directly in emBASIC: they can implement new built-in object types, and they can call C library functions and system calls.
From the mCAT point of view extension modules are shared libraries.

To support extensions, the emBASIC API (Application Programmers Interface) defines a set of functions, macros and variables that provide access to most aspects of the emBASIC run-time system. The emBASIC API is incorporated in a C source file by including the header "embasic.h". The compilation of an extension module depends on its intended use as well as on your system setup; details are given in the mCAT documentation “Shared Libraries”.

The Extension module exports one function which returns a pointer to a table of external functions for emBASIC. Refer to mCAT Kernel Reference, Chapter 6 to read how to create a shared library.
Note that the shared library ID must be 20h or higher to be available to the emBASIC runtime system.

17.1 A simple example

Let's create an extension module called "WrStr" and let's say we want to create an emBASIC interface to the mCAT library function WrStr().
This function takes a character string as argument and returns an integer. We want this function to be callable from emBASIC as follows:

status = WrStr("Hello world!")

Begin by creating a file module.c.
The first line of our file should be:

#include <embasic.h>

which pulls in the emBASIC API (you can add a comment describing the purpose of the module and a copyright notice if you like).
Since emBASIC may define some pre-processor definitions which affect the standard headers on some systems, you must include embasic.h before any standard headers are included.
The next thing we add to our module file is the C function that will be called when the emBASIC expression "WrStr(string)"is evaluated (we'll see shortly how it ends up being called):

/* C-Program example] */

17.2 The Module's Method Table and Initialization Function

Here we show how our function is called from emBASIC programs. First, we need to list its name and address in a method table:

exfun_t T[] = {
{NULL, NULL, 0, 0, NULL}

A method table contains the following elements:

Function name, character value;
Function address, void *;
Return type, emBASIC type value;
Number of input parameters, unsigned int value
Address of fun_arg_proto value, const;

The method table must be passed to emBASIC in the module's initialization function. The initialization function id must be 0.

17.3 Compilation and Linkage

### What files we need to create and how to compile

17.4 Uploading to the target

###: Which order and how to upload module to the target?

17.5 Calling emBASIC Functions from C

So far we have concentrated on making C functions callable from emBASIC. The reverse is also useful: calling emBASIC functions from C. This is especially the case for libraries that support so-called ``callback'' functions. If a C interface makes use of callbacks, the equivalent emBASIC often needs to provide a callback mechanism to the emBASIC programmer; the implementation will require calling the emBASIC callback functions from a C callback. Other uses are also imaginable.
Unfortunately current implementation of emBASIC API does not provide mechanism for calling emBASIC functions from C.

17.6 Defining new types

emBASIC allows the writer of an extension module to define new types that can be manipulated from emBASIC code, much like strings and structures in core emBASIC.

17.7 The basics

The emBASIC runtime sees all emBASIC objects as variables of type pool_object_t . An object contains the refcount (?) and a pointer to the object's ``type object''. This is where the action is; the type object determines which (C) functions get called when, for instance, an attribute gets looked up on an object or it is multiplied by another object.
Lets call these C functions ``type methods'' to distinguish them from things overloading which we will call ``object methods''.

17.8 Type methods

This section aims to give a quick fly-by on the various type methods you can implement and what they do.
Here is the definition of type_object_t:

### ToDo

So, if you want to define a new object type, you need to create a new type object.

17.9 Finalization and De-allocation

This function is called when the reference count of the instance of your type is reduced to zero and the emBASIC interpreter wants to reclaim it. If your type has memory to free or other clean-up to perform, put it here. The object itself needs to be freed here as well.

17.10 Attribute management functions

The getattr handler is called when the object requires an attribute look-up.
A likely way to handle this is (1) to implement a set of functions, (2) provide a method table listing these functions, and (3) provide a getattr() function that returns the result of a lookup in that table.
The setattr() handler is called when the attribute needs to be changed or deleted.

### When an attribute should be deleted

17.11 Object comparison

The compare handler is called when comparisons are needed and the object does not implement the specific rich comparison method which matches the requested comparison.