Основной файл (main file)

Основной файл компонент - это исходный файл, который :

Имя этого файла обычно main.c (или main.cpp , если ваш компонент написан на C++), и имя его файла заголовков main.h.

Доступ к интерфейсу программирования Gambas

Для доступа к интерфейсу программирования Gambas вам нужно :

Глобальная структура должна объявляться следующим образом :

  GB_INTERFACE GB;

Исходный файл должен ссылаться на эту структуру следующим образом :

  extern GB_INTERFACE GB;

Поскольку каждый исходный файл должен ссылаться на GB интерфейс и включать (include) gambas.h файл, самый легкий путь - положить их в в main.h файл, объявить GB в main.c, и включить (include) main.h везде.

Так что main.h будет выглядеть похожим на это :

  /* main.h */

#ifndef __MAIN_H
#define __MAIN_H

#include "gambas.h"

#ifndef __MAIN_C
extern GB_INTERFACE GB;
#endif

...

#endif

А main.c будет похож на это :

  /* main.c */

#define __MAIN_C

#include "main.h"

...

GB_INTERFACE GB;

...

Объявление классов компонент

Каждый класс, который вы реализуете в вашем компоненте, имеет его собственное описание структуры, объявленное в его собственном исходном файле. Эта структура объявлнеа в файле заголовков исходного файла класса.

Так что, вам надо включить (include) каждый файл заголовков класса в main.c :

  /* main.c */

#define __MAIN_C

#include "main.h"

#include "FirstClassSourceFile.h"
#include "SecondClassSourceFile.h"
...

GB_INTERFACE GB;

...

Затем вы должны объявить глобальный нуль-завершаемый (null-terminated) массив, который будет содержать указатель на каждую структуру класса, объявленную во включенных файлах загловков. Имя этого массива должно быть GB_CLASSES.

Примечание : исходный файл класса может объявлять и реализовывать более одного класса.

См. Writing a class , где больше инофрмации об исходных файлах класса.

  /* main.c */

...

GB_INTERFACE GB;

GB_DESC *GB_CLASSES[] =
{
FirstClassDescription,
SecondClassDescription,
ThirdClassDescription,
...,
NULL
};

Инициализация и выход из компонента

Компонент должен экспортировать две глобальные функции : первая вызывается, когда интерпретатор загружает компоненнт, а вторая вызывается, когда интерпретатор выгружает его.

Имя функции, вызваемой при загрузке должно быть GB_INIT.

  /* main.c */

...

int GB_INIT(void)
{
...
}

Эта функция не получает аргументов, и должна вернуть ненулевое целое значение, чтобы сказать интерпретатору, что он должен держать обшие библиотеки компонента в памяти после выгрузки.

Примечание : некоторые общие библиотеки (shared libraries), как X-Window библиотека, могут порушить процесс, если они выгружаются до окончания. Поскольку QT библиотека используется X-Window библиотекой, QT компонент должен удерживаться в памяти при выгрузке.

Основная работа GB_INIT() - объявить ловушки интерпретатора.

Как для вызова функции, при выгрузке компонента ее имя должно быть GB_EXIT.

  /* main.c */

...

void GB_EXIT(void)
{
}

...

Эта функция не принимает аргументы и ничего не возвращает. Она обычно ничего не делает, но вы можете использовать ее для предоставления специфических деинициализаций.

Ловушки интерпретатора (hooks)

Ловушки интерпретатора должны быть объявлены пока выполняется функция GB_INIT().  Следовательно, функции ловкушек обычно реализуются в  main.c файле.

Например, вот компонента QT функция GB_INIT() :

  /* main.cpp of QT component */

int GB_INIT(void)
{
GB.Hook(GB_HOOK_MAIN, (void *)my_main);
GB.Hook(GB_HOOK_LOOP, (void *)my_loop);
GB.Hook(GB_HOOK_WAIT, (void *)my_wait);
GB.Hook(GB_HOOK_WATCH, (void *)my_watch);
GB.Hook(GB_HOOK_POST, (void *)my_post);

return 1;
}

Чтобы получить больше информации о ловушках, обратитесь к The interpreter hooks

C++ специфические примечания

Вкратце, компонент должен экспортировать четыре символа в интерпретатор : GB, GB_CLASSES, GB_INIT и GB_EXIT.

Если вы программируете компонент на C++, вы должны оградить эти символы от extern "C" { and } , так чтобы линковщик C++ не преобразовал их имена.

Вот выдержка из main.cpp файла QT компонента :

  extern "C" {

GB_DESC *GB_CLASSES[] =
{
...
};

...

int GB_INIT(void)
{
GB.Hook(GB_HOOK_MAIN, (void *)my_main);
GB.Hook(GB_HOOK_LOOP, (void *)my_loop);
GB.Hook(GB_HOOK_WAIT, (void *)my_wait);
GB.Hook(GB_HOOK_WATCH, (void *)my_watch);
GB.Hook(GB_HOOK_POST, (void *)my_post);

return 1;
}

void GB_EXIT()
{
...
}

} /* extern "C" */

Большая картинка

  /* example of main.c */

#define __MAIN_C

#include "main.h"

#include "FirstClassSourceFile.h"
#include "SecondClassSourceFile.h"
#include "ThirdClassSourceFile.h"

GB_INTERFACE GB;

GB_DESC *GB_CLASSES[] =
{
FirstClassDescription,
SecondClassDescription,
ThirdClassDescription
NULL
};

static void my_error(int code, char *error, char *where)
{
...
}

int GB_INIT(void)
{
GB.Hook(GB_HOOK_ERROR, (void *)my_error);

return 0;
}