Основной файл компонент - это исходный файл, который :
Имя этого файла обычно main.c
(или main.cpp
, если ваш компонент написан на C++), и имя его файла заголовков main.h
.
Для доступа к интерфейсу программирования Gambas вам нужно :
gambas.h
в каждый исходный файл
компонента.
GB
, что получит интерфейс.
GB
символ.
Глобальная структура должна объявляться следующим образом :
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)
{
}
...
Эта функция не принимает аргументы и ничего не возвращает. Она обычно ничего не делает, но вы можете использовать ее для предоставления специфических деинициализаций.
Ловушки интерпретатора должны быть объявлены пока выполняется
функция 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
Вкратце, компонент должен экспортировать четыре символа в
интерпретатор : 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;
}