![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
User Defined Function в Interbase
AlexPul © (2003-09-08 12:05:00)
Подскажите как правильно создать работающую функцию. Я перепробовал все варианты из всех книг, что у меня были. Я делаю так. Создаю библиотеку с функцией
library MyUDF;
Function ANKLIKE(str1,str2 :string): Double; cdecl; export;
begin
......
end;
exports
ANKLIKE;
end.
Затем создаю саму функцию
DECLARE EXTERNAL FUNCTION ANKLIKE
VARCHAR (25),
VARCHAR (25)
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT "AnkLike" MODULE_NAME "MyUDF.dll";
До этого момента все отлично. Затем пытаюсь вызвать функцию в SQL и получаю ошибку:
Invalid token.
invalid request BLR at offset 60.
function ANKLIKE is not defined.
module name or entrypoint could not be found.
В чем проблема понять не могу. Я уже все перепробовал. Подскажите пожалуйста.
Digitman (2003-09-10 14:18:00) [1]
не выдумывай
вот выдержка из официального мануала
InterBase 6
Language Reference
strlen
Returns the length of a the input string.
DECLARE EXTERNAL FUNCTION STRLEN
CSTRING(32767)
RETURNS INTEGER BY VALUE
ENTRY_POINT ’IB_UDF_strlen’ MODULE_NAME ’ib_udf’;
как видишь, CSTRING - вполне легальный тип параметра
и с чего ты взял что сообщение об Unknown data type имеет отношение именно к CSTRING ? может у тебя запрос неверно составлен ?
AlexPul (2003-09-10 14:03:00) [2]
Вариант с cstring(100) у меня не работает, выдается сообщение Unknown data type
Digitman (2003-09-10 14:00:00) [3]
DECLARE EXTERNAL FUNCTION ANKLIKE
cstring(100),
cstring(100),
INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT "ANKLIKE" MODULE_NAME "ankudf";
в DLL
Function ANKLIKE(s1, s2: PChar; varPorog: Longint): Longint; CDECL; export;
BEGIN
// ShowMessage(Format(""%s" "%s" "%d"", [s1,s2,Porog])); никаких ShowMessage ! Это недопустимо !
END;
AlexPul (2003-09-10 13:33:00) [4]
Извините конечно, я уже наверное всех достал.
Я сам прекрасно все понимаю, но хоть убей не удается получить в DLL параметры функции
DECLARE EXTERNAL FUNCTION ANKLIKE
VARCHAR (100),
VARCHAR (100),
INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT "ANKLIKE" MODULE_NAME "ankudf";
в DLL
Function ANKLIKE(s1, s2: PChar; Porog: Longint): Longint; CDECL; export;
BEGIN
ShowMessage(Format(""%s" "%s" "%d"", [s1,s2,Porog]));
END;
в результате получаю сообщение, состоящее из мусора.
если бы не специфика задачи, то проще сделать тупым фильтром, при условии малого размера таблиц...
Digitman (2003-09-10 13:10:00) [5]
> AlexPul
ясно.
какого бы типа (строкового, имеется ввиду) ни было поле "aaaaaaa", перед передачей в UDF оно будет автом-ки преобразовано сервером в тот строковый тип, который указан в DDL-декларации соотв.параметра ф-ции
AlexPul (2003-09-10 12:53:00) [6]
Table1 - таблица
aaaaaaa - поле VARCHAR (100)
Digitman (2003-09-10 12:45:00) [7]
> "Table1"."aaaaaaa"
что-то мне непонятна вот эта конструкция
поясни, что это такое
AlexPul (2003-09-10 12:22:00) [8]
> Digitman
Не подскажешь, как правильно сделать приведение типа в самой DLL, если я передаю в качестве первого параметра значение поля таблицы VARCHAR(100), в качестве второго - STRING из SQL запроса,в качестве третьего - значение INTEGER из SQL запроса.
Т.е. запрос выглядит так:
select COUNT(*) from "Table1" where
anklike("Table1"."aaaaaaa", :SV, :PR)=1
Digitman (2003-09-08 17:28:00) [9]
> AlexPul
> Оказывается, что в UDF НЕЛЬЗЯ передавать строки, т.е. VARCHAR
> (..).
да ничего подобного)
и CHAR() можно, и VARCHAR()
другой вопрос, что - верно ты подметил - любой стандартный для IB тип строковых данных д.б. объявлен в UDF DLL как PChar
в случае передачи фактического CHAR-параметра в UDF попадет PChar-указатель на первый символ параметра-строки
в случае передачи фактического VARCHAR-параметра в UDF попадет PChar-указатель не на первый символ параметра-строки, а на счетчик символов (WORD), в котором лежит размер строки. Собссно строка будет находиться по смещению +2 от адреса, который был передан как PChar
AlexPul (2003-09-08 17:12:00) [10]
Я нашел решение.
Оказывается, что в UDF НЕЛЬЗЯ передавать строки, т.е. VARCHAR (..). Нужно обязательно как PCHAR
Например
Function ANKLIKE(s1,s2: PChar; Porog: Single): Longint; cdecl; export;
AlexPul (2003-09-08 13:29:00) [11]
Я сейчас все заново проверю.
Спасибо за помощь.
Zacho (2003-09-08 13:23:00) [12]
> AlexPul (08.09.03 13:20) [11]
Единственное, могу еще раз повторить:
Ну либо все-таки dll лежит где-то не там, либо ошибка или в имени функции, или в имени модуля, либо commit после этого не сделал.
Других вариантов не вижу.
AlexPul (2003-09-08 13:20:00) [13]
Firebird 1.0.3.972 for Win32
Zacho (2003-09-08 13:04:00) [14]
> AlexPul (08.09.03 13:00) [9]
Ну я же просил для стандартной ABS (IB_UDF_abs) из ib_udf.dll а не из некой неизвестной мне udflib.dll Да, версия IB какая ?
AlexPul (2003-09-08 13:00:00) [15]
> И приведи свой нерабочий DECLARE .. для стандартной ABS
> из ib_udf.dll
Он стандартный
DECLARE EXTERNAL FUNCTION abs
DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT "fn_abs" MODULE_NAME "udflib";
Zacho (2003-09-08 12:47:00) [16]
> AlexPul (08.09.03 12:42) [7]
Ну либо все-таки dll лежит где-то не там, либо ошибка или в имени функции, или в имени модуля, либо commit после этого не сделал. Да, еще вариант, попробуй так: ENTRY_POINT "ANKLIKE" MODULE_NAME "MyUDF";
И приведи свой нерабочий DECLARE .. для стандартной ABS из ib_udf.dll
AlexPul (2003-09-08 12:42:00) [17]
>Zacho
DECLARE EXTERNAL FUNCTION ANKLIKE
VARCHAR (25),
VARCHAR (25)
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT "ANKLIKE" MODULE_NAME "MyUDF.dll";
Zacho (2003-09-08 12:37:00) [18]
> AlexPul (08.09.03 12:31) [5]
А оно всегда нормально отрабатывает.
А commit после DECLARE .. сделал ? dll с UDF лежит в каталоге \UDF ?
Приведи свой DECLARE ... для ABS хотя бы.
AlexPul (2003-09-08 12:31:00) [19]
>Zacho
сменил, все равно не помогло.
Что самое главное, я даже стандартные функции (ABS, SIN...) не могу вызвать, хотя
DECLARE EXTERNAL FUNCTION ... отрабатывает нормально
Zacho (2003-09-08 12:20:00) [20]
Обрати внимание:
exports
ANKLIKE;
но
ENTRY_POINT "AnkLike"
Имя функции - регистрозависимое, регистр должен совпадать. Т.е. правильно будет так:
ENTRY_POINT "ANKLIKE"