Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 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
1-95323
Snake bite
2002-07-17 22:47
2002.07.29
<b>С добрым временем суток</b>


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


3-95212
Гас
2002-07-08 09:49
2002.07.29
Простой и красивый способ распространения проги с базой под IB


1-95279
roman002
2002-07-17 11:21
2002.07.29
Сканирование дерева каталогов


1-95424
Руль
2002-07-15 19:11
2002.07.29
Автоматический запуск Excel





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский