dev • overview

How To Program Components In C/C++


What is a component?

Gambas components are shared libraries written in C or C++ that add new functions to the Gambas interpreter.

They act like Linux drivers towards the Linux kernel:

A component can contain:

A component must have a name. This name is the the word gb followed by a dot-separated list of words describing the role of the component and another component it relies on, if any.


The Gambas Programming Interface

The Gambas Programming Interface is a set of utilities, functions and macros that allows you to:

The use of this programming interface is highly recommended, as it prevents a component from doing weird things.

The Gambas Programming Interface is a C structure that contains one function pointer for each function of the interface.

This structure is declared in the main file of your component and is automatically initialized by the interpreter at component loading.

Writing Good Components

Writing good components is the difficult part! Let's suppose you want to write a SDL component, i.e. a component that lets a Gambas project use all the power of the SDL library: graphics, sound, CD-ROM...

You can be happy with just wrapping the library functions, structure and constants. It is the easy way, even if wrapping C structures and functions may not be possible in every case with Gambas.

Your component will be useful, but not very interesting for the Gambas programmer, because he will have to program in C or C++ style.

Instead, you should rack your brain to create a different interface between Gambas and the library, by trying to generalize and simplify the original interface of the library.

That is what I did with qt: it is far easier to use the gb.qt4 component than programming the Qt library directly. Moreover, the gb.gtk component use the same interface than gb.qt4, and so you can write a GUI program that can use one or the other indifferently.

Component Source Organization

The source files of a component are stored in its own directory.

Use the first case if your component needs one or more shared library.

Use the other one if your component just needs a very basic library already used by the interpreter, like libc or libm.

A typical component directory includes:

Here is the contents of the gb.dbus directory that is not generated by the autoconf/automake tools:

├── acinclude.m4 -> ../acinclude.m4                         Common autoconf macros
├── AUTHORS                                                 File required by GNU tools
├── ChangeLog                                               File required by GNU tools
├── -> ../                part needed by components
├──                                            The autoconf configuration file
├── gambas.h -> ../main/share/gambas.h                      The Gambas interpreter API header
├── gb_common.h -> ../main/share/gb_common.h                Some other useful common declarations
├── INSTALL -> ../INSTALL                                   File required by GNU tools
├── m4 -> ../m4                                             Directory including common m4 macros used by and acinclude.m4
├──                                             The top-level automake configuration file
├── missing -> ../missing                                   File required by GNU tools
├── NEWS                                                    File required by GNU tools
├── README                                                  README file
├── reconf -> ../reconf                                     Link at a script that reconfigure the source package from scratch
└── src                                                     The source directory
    ├── c_dbus.c
    ├── c_dbusconnection.c
    ├── c_dbusconnection.h
    ├── c_dbus.h
    ├── c_dbusobserver.c
    ├── c_dbusobserver.h
    ├── c_dbusvariant.c
    ├── c_dbusvariant.h
    ├── dbus_print_message.c
    ├── dbus_print_message.h
    ├── gb.dbus                                             The Gambas part of the gb.dbus component
    │   ├── .project
    │   └── .src
    │       ├── CTest2.class
    │       ├── CTest.class
    │       ├── DBusApplication.class
    │       ├── DBus.class
    │       ├── DBusObject.class
    │       ├── DBusProxy.class
    │       ├── DBusSignal.class
    │       └── MMain.module
    ├── gb.dbus.component                                    The component description file
    ├── helper.c
    ├── helper.h
    ├── main.c
    ├── main.h
    └──                                          The automake configuration file of the "src" sub-directory

There is a TEMPLATE directory in the sources that includes a script named make-component that can create a component skeleton directory from a configuration file.

The configuration file must be located in the TEMPLATE/conf sub-directory.

See the TEMPLATE/README file for more details.