library TestUDF;
uses SysUtils;
function malloc(Size: Integer): Pointer; cdecl; external
'msvcrt.dll';
function StrUpperCase(sz: PChar): PChar; cdecl; export;
var Tmp: string;
begin
Tmp := AnsiUpperCase(sz);
Result := malloc(length(Tmp) + 1);
StrPCopy(Result, Tmp);
end;
exports
StrUpperCase;
begin
end.
Динамическая библиотека экспортирует только одну функцию: StrUpperCase. Для передачи строковых параметров, равно как и результата функции, используется тип Pchar, т е. динамическая строка, ограниченная символами #0. Смысл кода нашей функции очевиден: мы приводим строку sz у верхнему регистру, используя стандартную функцию AnsiUpperCase. Данная функция корректно работает с русскими буквами, если в системе установлена русская кодовая страница. После этого выделяем память для результирующей переменной, используя malloc - стандартную функцию Windows. Остается только скопировать значение временной переменной Tmp в переменную Result. Скомпилируйте библиотеку и поместите полученный файл TestUDF.dll в нужный каталог. Если вы используете InterBase 6.x или его клоны, то это каталог \Udf, который находится в каталоге установки сервера. Необходимо зарегистрировать функцию в базе данных. Для регистрации необходимо выполнить команду DECLARE EXTERNAL FUNCTION, которая имеет следующий синтаксис:
DECLARE EXTERNAL FUNCTION name [datatype | CSTRING (int)
[, datatype | CSTRING (int) ...] ]
RETURNS (datatype [BY VALUE] | CSTRING (int)} [FREE_IT]
ENTRY_POINT 'entryname'
MODULE_NAME ' modulename';
Параметр name - это имя пользовательской функции внутри базы данных. Он не обязательно должен совпадать с реальным названием функции в DLL.
Параметр datatype определяет тип параметров. На параметры накладываются следующие ограничения:
* все параметры передаются по ссылке;
* выходной параметр (значение функции) может возвращаться по значению;
* параметры не могут быть массивами.
Если вы хотите применять строковые параметры, то вы должны использовать тип CSTRING В скобках необходимо указать максимальную длину строки. Если строка является результатом функции, она всегда передается по ссылке, а не по значению.
Параметр FREE_IT указывает InterBase, что после выполнения функции необходимо автоматически освободить память, выделенную для параметров. Очевидно, данная опция нужна только в том случае, если наша библиотека сама мм делила память под какие-либо параметры функции.
В параметре entryname необходимо указывать название функции в DLL, ко торую мы собственно и хотим декларировать как пользовательскую функцию.
В параметре modulename необходимо указать название файла DLL, в котором находится декларируемая функция пользователя.
Стоит заметить, что параметры entryname и modulename регистрочувствительные.
Таким образом, чтобы добавить нашу функцию в базу данных, нам необходимо выполнить следующую команду:
DECLARE EXTERNAL FUNCTION USTRUPPERCASE
cstring(254)
RETURNS cstnng(254) FREE_IT
ENTRY_POINT 'StrUpperCase' MODULE_NAME 'TestUDF.dll'
После этого мы сможем использовать новую функцию USTRUPPERCASE в любом SQL-запросе. Например, мы можем проверить, как работает функция на следующем запросе: