Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.07.29;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.017 c
1-95413
Loco
2002-07-16 12:44
2002.07.29
Закладки


14-95499
JohnnyJ
2002-06-30 23:00
2002.07.29
Посоветуйте какой TV-tuner брать


4-95625
ЛенаК
2002-05-21 09:54
2002.07.29
Проблема с функцией StringToWideChar


3-95237
MikeP
2002-07-08 18:29
2002.07.29
TSocketConnection не завершается работа Windows


14-95501
Партизан
2002-07-01 14:14
2002.07.29
Емулятор.