При распределении памяти под возвращаемые значения для обеспечения потокобезопасности и переносимости следует использовать функцию ib_ut.ii_maiioc(). Вместе с ней нужно применять также ключевое слово FREE_IT В предложении RETURNS при объявлении функции, которая возвращает динамически создаваемые объекты.
В следующем примере сервер Firebird освободит буфер, если UDF была определена с зарезервированным словом FREE IT. Обратите внимание, что этот пример использует функцию Firebird ib_utii_maiioc() для выделения памяти:
char *fn_lower(char *ups) {
char *buffer = (char *) ib util_malloc(256);
return (buffer); }
Вот ее объявление:
DECLARE EXTERNAL FUNCTION lowercase VARCHAR (25 6)
RETURNS CSTRING(256) FREE_IT
ENTRY POINT 'fn lower' MODULE_NAME 'ib_udf';
! ! !
ПРИМЕЧАНИЕ. Память должна освобождаться той же библиотекой времени выполнения, которая выделяла эту память.
. ! .
Когда модуль UDF готов, компилируйте его обычным образом в объектный или библиотечный формат.
Включите ibase.h или его эквивалент, если вы используете в нем объявления типов.
Если сборка выполняется статически, свяжите модуль с клиентской библиотекой Firebird, если вы обращаетесь к какой-либо функции библиотеки Firebird. Для Microsoft Visual C/C++ библиотеки fbclient ms.lib и ib_util_ms.lib могут быть найдены в каталоге Firebird /lib.
Для включения UDF в существующий модуль внешней функции добавьте файл, содержащий объектный код новой UDF, и перекомпилируйте как обычно. Некоторые платформы позволяют добавлять объектные файлы непосредственно в существующие библиотеки. Относительно подробностей посмотрите документацию по компилятору и редактору связей для конкретной платформы.
Для удаления функции следуйте инструкциям редактора связей по удалению объектов из библиотеки. Удаление функции из библиотеки не удаляет ее объявления из базы данных - используйте для этого DROP EXTERNAL FUNCTION.
Функции BLOB отличаются от других внешних функций, потому что им передаются указатели па управляющие структуры BLOB, а не на фактические данные. Функция не может открывать и закрывать BLOB, а вместо этого вызывает функции API для выполнения доступа к BLOB.
Управляющая структура BLOB является структурой языка С, определенной в функциональном модуле в виде typedef. Программисты должны описать такую управляющую структуру на языке С, т. е. должны написать следующее:
typedef struct blob {
short (*blob_get_segment)();
isc_blob_handle blob_handle;
long number_segments;
long max_seglen;
long total_size;
void (*blob_put_segment)();
} *Blob;
Табл. 36.1 описывает поля в управляющей структуре BLOB.
Таблица 36.1. Поля в управляющей структуре BLOB[145]