Форум: "Базы";
Текущий архив: 2002.07.29;
Скачать: [xml.tar.bz2];
ВнизIB SQL UDF Найти похожие ветки
← →
Nebula (2002-07-05 14:51) [0]Продолжение вопроса. Библиотеку создал, функция возвращает строку.
function MyUDF: string;
begin
result := "text";
end;
в IB описал.
DECLARE EXTERNAL FUNCTION NEBULA
RETURNS VARCHAR(1024) CHARACTER SET WIN1251
ENTRY_POINT "MyUDF"
MODULE_NAME "path\MyUDF.dll"
Как вызвать-то? select MyUDF не работает.
← →
Val (2002-07-05 15:02) [1]а почему вы так ее вызываете? вы же select sum не пишите, к примеру?
← →
Johnmen (2002-07-05 15:03) [2]1. dll должна лежать в соотв. месте
2. Может всетаки использовать уже существующие библиотеки ?
← →
kaif (2002-07-05 15:10) [3]Нужно аллокировать память (GetMem) под строку, PChar возвращать, а не string и использовать FREE_IT в объявлении UDF. Функцию объявить как stdcall и экспортировать из dll (export).
← →
Nebula (2002-07-05 15:42) [4]2Johnmen. С огромным удовольствием! Какую библиотеку использовать?
← →
Johnmen (2002-07-05 15:48) [5]ib_udf.dll
← →
Digitman (2002-07-05 17:35) [6]Небольшое замечание к kaif © (05.07.02 15:10)
спецификатор free_it вовсе не является обязательным при возврате чего-либо, в дан. случае - строки.
данный спецификатор требуется для указания IB-ядру сервера о необходимости автоматически освобождать блок памяти выделенный в теле UDF для передачи некоего (произвольного типа, в 1-ю очередь - строкового) возвращаемого параметра, после того, как значение возвращенного параметра буде считано из результирующего блока памяти. Если этого не сделать, возникнут утечки памяти и последствия работы сервера будут непредсказуемыми.
← →
kaif (2002-07-05 17:46) [7]>2 Digitman.
Я знаю. Правда я думал, что FREE_IT используется исключительно для строк...
Кстати, спасибо за пример FormatDateTime. Он заработал.
Потом немного мучился с FormatFloat...
В конце концов удалось наконец принять в dll тип
DOUBLE PRECISION:
function FmtIBDouble(FmtStr: PChar; Value: Pointer): PChar; stdcall;
var
Tmp: String;
begin
try
Tmp:= FormatFloat(String(FmtStr), Double(Value^));
...и т.д.
Странно, но передача по ссылке (const Value: double) не работала. Я уже не первый раз с этим сталкиваюсь при работе с dll. Разве это не то же самое, что и разыменование указателя?
Видно я чего-то фундаментального не знаю о передаче параметров по ссылке...
← →
Digitman (2002-07-05 18:22) [8]>>фундаментального не знаю о передаче параметров по ссылке...
Эт точно) ... но - самокритично и вызывает неподдельное уважение.
Правило №1 (выучи как Отче Наш - очень поможет в дальнейшем):
абсолютно все факт.параметры передаются ядром IB-сервера в UDF ссылкой (указателем) на местоположение в АП сервера ВРЕМЕННОЙ КОПИИ оригинальных параметров.
Отсюда прямой вывод :
Объявление параметров в самой UDF должно делаться ,как минимум, двумя способами (возьмем для примера тот же Double)
1. var Value: Double
2. [const] Value: PDouble, где PDouble = ^Double;
[const] - необязательный спецификатор, разницы в том, есть он или отсутствует, в случае с UDF - абсолютно никакой
Соответственно, обращение из UDF к заначениям переданных параметров должно выглядеть след.образом :
1. SomeLocalVar := Value;
2. SomeLocalVar := Value^; вот оно, разыменование прямого указателя
Дабы не влипнуть в AV, следует еще и такую вещь всегда принимать во внимание : если передаваемый факт.параметр = Null, то в UDF передается nil, а проверить это во избежание AV оч.просто :
1. if Assigned(@Value) then ...
@ - это перекрытие действий компилятора по-умолчанию, который без "барана" в лучшем случае будет проверять на nil не переданную ссылку, а то что лежит фактически по этой ссылке, в худшем - вообще откажется компилировать
2. if Assigned(Value) then ...
Еще один важный момент : никаких stdcall в декларации экспортируемых ф-ций ! Только cdecl будет работать правильно ! Почему ? Загляни в хэлп в топик "calling conventions" - сразу станут ясны различия с учетом того, что IB-ядро использует C-соглашения о вызовах и балансе стека при возврате из вызываемой cdecl-ф-ции
← →
Digitman (2002-07-05 18:28) [9]Небольшое уточнение : правило передачи Null-параметров на строковые параметры не распространяется, и if Assigned(..) в таких случаях всегда даст True, потому как передается адрес ВРЕМЕННОГО блока памяти, содержащего на момент вызова UDF единственный символ - #0 (терминатор строки)
← →
kaif (2002-07-06 02:26) [10]>2 Digitman
Спасибо за подробные объяснения. Особенно насчет способа вызова. Дело в том, что у меня вызовы stdcall срабатывают в Interbase и мои UDF-ы работают без видимых признаков проблем. Мне и в голову не пришло, что IB требует cdecl. Я по привычке вписал stdcall. Я знал разницу в принципах этих вызовов, но мне казалось, что все приложения Win32 как правило используют stdcall, по крайней мере все API. А вот, выясняется, что IB действует иначе...
Сейчас еще посмотрю, что у меня с NULL происходит (забыл проверить). То есть строковый NULL это просто пустая строка? Но ведь IB различает значения "" и NULL. Или это только при передаче параметров то же самое?
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2002.07.29;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.006 c