Первый раз UDF

ЧАстые Вопросы и Ответы

Модераторы: kdv, CyberMax

Leons
Сообщения: 29
Зарегистрирован: 24 фев 2006, 08:29

Первый раз UDF

Сообщение Leons » 05 фев 2007, 17:34

Выручайте...

Код: Выделить всё

library my_udf;
uses
  SysUtils,
  Classes;
var 
  ResultInteger: Integer;

function AnalysisStr(var Str:String; var ItemIndex:SmallInt; var ItemCount:SmallInt):PInteger; cdecl; export;
var
  S: TStringList;
begin
  S:= TStringList.Create;
  S.DelimitedText := Str;
  S.Delimiter := ',';
  ItemCount := S.Count;
    if ItemCount >= ItemIndex Then ResultInteger := StrToInt(S.Strings[ ItemIndex ])
    else ResultInteger := -10;
  S.Free;
  Result := @ResultInteger;
end;

exports
  AnalysisStr;

begin
end.

Код: Выделить всё

DECLARE EXTERNAL FUNCTION NEW_UDF
    VARCHAR(250),
    SMALLINT,
    SMALLINT
RETURNS SMALLINT FREE_IT
ENTRY_POINT 'AnalysisStr' MODULE_NAME 'my_udf'
При вызове разрывается соединение с сервером

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 05 фев 2007, 18:03

Читал? Перечитай ещё раз.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 05 фев 2007, 18:32

интересно, почему так трудно учиться на примерах?
Где в примерах, статьях или документации сказано, что в udf можно передавать string? И зачем передавать integer по указателю ???

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 05 фев 2007, 18:59

Кстати, использовать глобальную переменную в UDF - это не просто плохо, а очень плохо.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 05 фев 2007, 19:16

и писать бред вроде returns smallint free_it - тоже. Одновременно передавая на выход PInteger.

в общем, если бы автор еще и stdcall функцию сделал, то был бы абсолютно полный комплект ошибок из разряда "как не надо писать udf".

Leons
Сообщения: 29
Зарегистрирован: 24 фев 2006, 08:29

Сообщение Leons » 06 фев 2007, 09:54

Сори) Но про глобальную переменную вычитал в статье именно на этом сайте) Написано, что глобальная переменная сбрасывает значение в самый последний момент, в отличии от локальной. При использовании локальной переменной в некоторых случаях возвращается пустое значение.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 06 фев 2007, 10:02

написано, что глобальная переменная сбрасывает значение в самый последний момент, в отличии от локальной. При использовании локальной переменной в некоторых случаях возвращается пустое значение.
не в карты, а в шахматы, и не выиграл, а проиграл.

скорее всего там написано вообще не то. как минимум, там должно быть написано, что глобальными переменными в udf можно пользоваться только в архитектуре Classic.
Пожалуйста, или не читай по диагонали, или дай точную цитату, чтобы я посмотрел и проверил.

Ну а насчет остальных ошибок что? :)

Leons
Сообщения: 29
Зарегистрирован: 24 фев 2006, 08:29

Сообщение Leons » 06 фев 2007, 10:10

Код: Выделить всё

library my_udf;

uses
  SysUtils,
  Classes;

function AnalysisStr(var Str:PChar; var ItemIndex:SmallInt; var ItemCount:SmallInt):Integer; cdecl; export;
var
  S: TStringList;
begin
  S:= TStringList.Create;
  S.DelimitedText := Str;
  S.Delimiter := ',';
  ItemCount := S.Count;
    if ItemCount >= ItemIndex Then Result := StrToInt(S.Strings[ ItemIndex ])
    else Result := -10;
  S.Free;
end;

exports
  AnalysisStr;

begin
end.

Код: Выделить всё

DECLARE EXTERNAL FUNCTION MY_UDF
    VARCHAR(250),
    SMALLINT,
    SMALLINT
RETURNS INTEGER BY VALUE
ENTRY_POINT 'AnalysisStr' MODULE_NAME 'my_udf'
Не работает)

UDF - Зло;)
Мне подсказали иной выход из ситуации)
http://forum.ibase.ru/phpBB2/viewtopic.php?t=3359

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 06 фев 2007, 10:25

Leons писал(а):

Код: Выделить всё

var Str:PChar;ode]
    VARCHAR(250),
UDF - Зло;)
Думать меньше надо, больше читать документацию. Ну вот с какой балды ты решил что PChar и VarChar совместимы???

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 06 фев 2007, 10:36

Мне подсказали иной выход из ситуации
понятно что подсказали. но ты как писал UDF "с ашипками", так и продолжаешь. Причем с ошибками по причине элементарной НЕВНИМАТЕЛЬНОСТИ.

Leons
Сообщения: 29
Зарегистрирован: 24 фев 2006, 08:29

Сообщение Leons » 06 фев 2007, 10:39

Dimitry Sibiryakov писал(а):
Leons писал(а):

Код: Выделить всё

var Str:PChar;ode]
    VARCHAR(250),
UDF - Зло;)
Думать меньше надо, больше читать документацию. Ну вот с какой балды ты решил что PChar и VarChar совместимы???
В вышеприведенных примерах мы использовали переменные типа integer, smallint – эти типы полностью совпадают в IB и Delphi.
А вот таблица соответствия остальных типов данных:
type
C, C++, Delphi InterBase
------------- ------------- ----------------
Short SmallInt SmallInt
Long Longint Integer
int Integer Integer
Float Single Float
Double Double Double precision
*void, *char PChar Char(???), VarChar(???), CString

http://www.ibase.ru/devinfo/udf_ok.htm

Leons
Сообщения: 29
Зарегистрирован: 24 фев 2006, 08:29

Сообщение Leons » 06 фев 2007, 10:40

покажите плизз, где ошибка...

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 06 фев 2007, 10:58

блин. при чем тут какое-то соответствие типов?

читай про передачу строк.

CString – это строка символов оканчивающаяся нулевым символом, т.е. типичная строка языка С (или Delphi PChar), что и видно из названия.

VarChar – это очень похоже на строку языка Pascal (или Delphi ShortString),
но имеет в начале не один, а два байта, представляющие длину строки.


Похоже, но в C/Pascal НЕТ эквивалента varchar и char, которые в IB/FB.
И в статье видно - как задекларирован параметр, и как он передается и обрабатывается в функции.
собственно, поэтому есть правило - всегда использовать для объявления udf CSTRING, и не парить мозг в функции, т.к. это будет обычный pchar что бы ты в функцию в SQL не передал. В статье об этом тоже написано.

p.s. статью подправлю, хоть и не моя. Но ты все равно один из первых, кто не так прочитал именно этот момент. Посмотрел бы мой пример,
www.ibase.ru/devinfo/safeudf.zip или другие, и увидел бы, что с параметрами varchar и char функции никто не объявляет.

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 06 фев 2007, 10:59

Leons писал(а):покажите плизз, где ошибка...
Знаешь, наверное проще будет сказать в какой строке ошибок нет...
Вот она, эта единственная строка:

Код: Выделить всё

else Result := -10;

Leons
Сообщения: 29
Зарегистрирован: 24 фев 2006, 08:29

Сообщение Leons » 06 фев 2007, 11:29

нет такого файла. www.ibase.ru/devinfo/safeudf.zip
Лана, замучал я Вас, буду позже сам осваивать UDF. Пока что без него обойдусь.

Dimitry Sibiryakov - злой ты

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 06 фев 2007, 11:50

1.

Код: Выделить всё

S:= TStringList.Create; 
try
...
finally
  S.Free;
end;
2. Зачем передавать в функцию ItemCount, если ей потом присваивается значение?

Leons
Сообщения: 29
Зарегистрирован: 24 фев 2006, 08:29

Сообщение Leons » 06 фев 2007, 11:57

1. Ты прав. В конечной "рабочей" версии так и будет
2. Она только для возврата значения.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 06 фев 2007, 11:59

нет такого файла.
www.ibase.ru/download/safeudf.zip

на сайте есть поиск. мог бы и сам по слову safeudf найти.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 06 фев 2007, 12:25

Leons писал(а):2. Она только для возврата значения.
Для возврата куда?
У тебя Result возвращается, зачем тебе ещё одна переменная входная?

Leons
Сообщения: 29
Зарегистрирован: 24 фев 2006, 08:29

Сообщение Leons » 06 фев 2007, 13:00

WildSery писал(а):
Leons писал(а):2. Она только для возврата значения.
Для возврата куда?
У тебя Result возвращается, зачем тебе ещё одна переменная входная?
Это еще одно возвращаемое значение для ХП, через которое планировалось определять количество элементов в :code, для обращения к ним без выхода за проделы.

Ребят, предлагаю закрыть тему. Эта процедурка писалась 10- секунд для теста UDF. Я обошелся без UDF. Так что почитаю повнимательнее про все это попозже.

Если кому не сложно, переделайте данный пример в рабочую версию. Я посмторю отличия)

Ответить