| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Firebird, Interbase > Соглашение вызова в UDF-библиотеке |
| Автор: Sister 17.5.2006, 01:55 |
| Проблема вот в чем. Создал UDF dll-ку, сервером функция из нее вызывается, возвращаемое значение адекватно получаему параметру, но вот сам параметр не передается (точнее передается что-то вроде его адреса). UDF: Тип параметра - INTEGER, возвращает CSTRING(30). Тестировал dll-ку в Delphi, все получается нормально, когда соглашения вызова совпадают и в библиотеке и в программе, но что касается сервера БД, то он при некоторых соглашниях вызова, установленных в библиотеке, отказывается работать. Какое соглашение должно быть? |
| Автор: TheCetus 17.5.2006, 09:44 |
| DECLARE EXTERNAL FUNCTION CET_POSEX CSTRING(250), CSTRING(32767), INTEGER RETURNS INTEGER BY VALUE ENTRY_POINT 'Cet_PosEx' MODULE_NAME 'cet_udf'; вроде на форуме где то лежала статья как UDFы писать Добавлено @ 09:45 DECLARE EXTERNAL FUNCTION CET_GET_PARAMITEM CSTRING(1), CSTRING(32767), INTEGER RETURNS CSTRING(250) FREE_IT ENTRY_POINT 'Cet_Get_ParamItem' MODULE_NAME 'cet_udf'; Добавлено @ 09:47 а еще лучше покажи скрипты регистрации функций, код самих функций и параметры при которых все падает |
| Автор: Sister 18.5.2006, 21:14 |
| Код dll: library Project2; uses SysUtils, Classes; {$R *.res} function GetNameOfPeriod(days: integer): PChar; export; begin //остальной код, первым делом проверяю days - оно вообще не то, которое передается end; exports GetNameOfPeriod; begin end. Скрипт регистрации: DECLARE EXTERNAL FUNCTION u_getname INTEGER RETURNS CSTRING(30) ENTRY_POINT 'GetNameOfPeriod' MODULE_NAME 'Project2'; Любой параметр типа integer передается неверно, например, так: SELECT rdate, content, tim, u_getname(tim) FROM requests; где tim определен как integer. Что интересно, так это то, что при соглашении вызова cdecl правильно передаются строки CSTRING(XXX), но неправильно - числа. А если соглашение принимается таким, какое оно по умолчанию, то вообще ничего из них не передается верно (пробовал только строки и числа). |
| Автор: TheCetus 19.5.2006, 12:10 | ||||
Добавлено @ 12:14 у меня при сипользовании cdecl все нормально передается |
| Автор: Sister 19.5.2006, 20:55 |
| 2TheCetus: передаешь INTEGER, а принимаешь byte. Почему? Хотя это и не имеет большого значения, я думаю. |
| Автор: Sister 19.5.2006, 21:44 | ||||||
Показательный пример:
Скомпилированная dll помещается в ...Firebird_1_5\UDF Скрипты БД:
Результаты следующего запроса:
TIM u_ReturnParam 3 17 692 540 5 17 692 540 2 17 692 540 7 17 692 540 7 17 692 540 2 17 692 540 3 17 692 540 1 17 692 540 3 17 692 540 2 17 692 540 3 17 692 540 |
| Автор: TheCetus 22.5.2006, 09:00 | ||
короче, вот решение:
все параметы передаваемые по значению должны именно так и передаваться ) т.е. параметры типа integer, byte должны быть описаны с VAR P.S. Посмотрел, у меня в проекте функция Cet_Char не использовуется, поэтому баг не заметил сразу |
| Автор: Sister 28.5.2006, 03:09 | ||
А уверен, что по значению, ведь var - это передача по ссылке. Я пробовал так делать, но не получалось может быть из-за того, что я изменял и соглашение и писал var безсистемно, не проверив всех вариантов, один из которых мог оказаться удачным. И чем параметры integer и byte так выделяются? И еще - чтобы передавать параметр не по ссылке, надо в объявлении функции в БД после указания его типа писать BY VALUE ? Так или иначе, это мне уже не нужно, но теперь просто интересно узнать, как все это правильно делается. |
| Автор: TheCetus 29.5.2006, 09:22 | ||||
| точно, описАлся... по ссылке... вот работающий код UDF функции
значение возвращается по значению, а не по ссылке передается по ссылке строки передаются как PChar... вприницпе тут где то была статья как писАть UDF функции, там все достаточно хорошо расписано... свою библиотеку писал по этой статье |