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

Вниз

Как сделать UDF   Найти похожие ветки 

 
Вася Добрый   (2003-12-29 12:18) [0]

Привет Всем! Возвращаюсь к своим баранам.
Задам до неприличия тупой вопрос:
Есть функция в DLL, функция такая

function nextdate (datn,datk:pdate):pdate;cdecl;
var d,m,y:Word;
r:integer;
dat:TDate;
begin
decodedate(datn^,y,m,d);
inc(m);
if m>12 then
begin
inc(y);
m:=1;
end;
d:=1;
dat:=encodedate(y,m,d)-1;
if dat>datk^ then
begin
r:=Trunc(datk^);
end
else
begin
r:=Trunc(dat);
end;
New(result);
result^:=r;
end;
Как её прицепить к базе данных в IBExpert"e в качестве UDF???????


 
Digitman ©   (2003-12-29 12:35) [1]

Вася, дорогой, по поводу твоих "баранов" я тебе уже неделю назад как ответ дал)... на предыдущий ТОТ ЖЕ вопрос)

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

а если не потерял, то не вник в нее полностью - переправил только stdcall на cdecl и засим успокоился почему-то ...

а ведь там я тебе по-русски сказал - форматы даты-времени в IB и ObjectPascal несовместимы ! И если на вход ф-ции подается значение даты-времени в формате IB (равно как и возвращается в кач-ве результата), то нужно выполнять промежуточные преобразования


> Как её прицепить к базе данных в IBExpert"e в качестве UDF


про синтаксис и использование в DDL-скриптах DECLARE FUNCTION - предложений что-нибудь слышал ?


 
Вася Добрый   (2003-12-29 12:49) [2]

Не ругайся, на меня нельзя ругаться.
С инфой у меня туго, ни литературы нет, ни спросить не у кого, да и связь с инетом хреновая.
В мухосранске мы живём, тёмные, забитые, голодаем...
Сами то мы не местные поможите чем можете

> И если на вход ф-ции подается значение даты-времени в формате
> IB (равно как и возвращается в кач-ве результата), то нужно
> выполнять промежуточные преобразования

Как выполнять?

> про синтаксис и использование в DDL-скриптах DECLARE FUNCTION
> - предложений что-нибудь слышал ?


Если бы я что нить слышал, то не спрашивал бы. Я вообще раньше UDF не юзал, вот захотел попробовать, только с какой стороны подойти не знаю


 
Digitman ©   (2003-12-29 13:13) [3]

ах, ну ты посмоти какие мы бедные-разнесчастные-то !!
прямо аж слеза прошибает)

uses IBHeader
....

const

MSecsPerDay10 = MSecsPerDay * 10; // миллисекунд в сутках * 10
IBDateDelta = 15018; // разница в днях между "нулевыми" датами OP и IB

function DateToQuad(d: TDateTime): TISC_QUAD;
var
Days: Integer;
begin
Days:= Trunc(d);
Result.gds_quad_high:= Days + IBDateDelta;
Result.gds_quad_low:= Trunc((d - Days) * MSecsPerDay10);
end;

function QuadToDate(ibd: TISC_QUAD): TDateTime;
begin
Result:= ibd.gds_quad_high - IBDateDelta + ibd.gds_quad_low / MSecsPerDay10;
end;

...
function nextdate ( var datn,datk: TISC_QUAD): TISC_QUAD; cdecl;
var
DateFrom, DateTo, DateResult: TDateTime;
begin
//преобразуем IB-дату/время в формат OP

DateFrom := QuadToDate(datn);
DateTo := QuadToDate(datk);

.. // здесь творишь с параметрами DateFrom, DateTo то что тебе нужно, и записываешь результат "творчества" в лок.переменную DateResult

//обратное преобразование рез-та

Result := DateToQuad(DateResult);

end;

...

DECLARE EXTERNAL FUNCTION nextdate
DATE, DATE
RETURNS DATE
ENTRY_POINT "nextdate" MODULE_NAME "МояUDF.dll"


 
Вася Добрый   (2003-12-29 13:23) [4]


> ах, ну ты посмоти какие мы бедные-разнесчастные-то !!
> прямо аж слеза прошибает)

Большое спасибо за сочуствие, сразу видно благородного человека.

> ENTRY_POINT "nextdate" MODULE_NAME "МояUDF.dll"

Не знаю почему, но если в IBExpert"e написать именно так , то не работает, а если не писать .dll, то всё нормально

ENTRY_POINT "nextdate" MODULE_NAME "МояUDF"

Попробую сделать так, как сказано свыше, заранее сардечно благодарю! (Есть же умные люди на земле!)


 
ИМХО ©   (2003-12-29 13:23) [5]

А Диджитман не может не ругаться. Это у него в крови. Цифровой крови.


 
Digitman ©   (2003-12-29 13:34) [6]


> то не работает


> то всё нормально


детский лепет)

ты программист или где !?

что, прямо так на экране и написано, мол, "не работает" или "все нормально" ?))


 
Вася Добрый   (2003-12-29 14:19) [7]


>
> Digitman © (29.12.03 13:13) [3]

Чего-то не прокатывает такая фишка. Мало того что никаких значений не возвращает, так ещё и ВСЕХ клиентов от сервера отрубает!!!
Что бы это значило???


 
Вася Добрый   (2003-12-29 14:24) [8]


> что, прямо так на экране и написано, мол, "не работает"
> или "все нормально" ?))

Имеется в виду, что без .dll хотя бы не посылает на "Access violation..."


> ты программист или где !?

Не совсем. Сисадмин.


 
Digitman ©   (2003-12-29 14:31) [9]

приводи полный текст DLL, текст IB-скрипта, c пом.которого ты объявил такую-то ф-цию в своей IB-базе, и текст SQL-предложения, в котором фигурирует обращение к этой UDF-ф-ции


 
Digitman ©   (2003-12-29 14:49) [10]

примерно так должно быть, если я правильно понял требуемую логику твоей UDF :

function nextdate (var datn,datk: TISC_QUAD): TISC_QUAD; cdecl;
var
Dat, DateFrom, DateTo, DateResult: TDateTime;
begin
DateFrom := QuadToDate(datn);
DateTo := QuadToDate(datk);
/////////////
decodedate(DateFrom,y,m,d);
inc(m);
if m>12 then
begin
inc(y);
m:=1;
end;
d:=1;
Dat:=encodedate(y,m,d) - 1;
if Dat > DateTo then
begin
DateResult := Trunc(DateTo);
end
else
begin
DateResult := Trunc(Dat);
end;
/////////////

Result := DateToQuad(DateResult);
end;

p.s.

результат ф-ции - 8-байтное значение в формате IB DATE - вполне м.б. возвращен серверу по значению, поэтому выделение памяти под результат не требуется, и уж тем более - не средствами менеджера памяти от Борланд


 
Вася Добрый   (2003-12-29 15:04) [11]


> приводи полный текст DLL

library dates;

uses
SysUtils,
Controls,
Classes,
IBHeader;

const

MSecsPerDay10 = MSecsPerDay * 10;
IBDateDelta = 15018;
type pdate=^Tdate;
{$R *.RES}
function DateToQuad(d: TDateTime): TISC_QUAD;
var
Days: Integer;
begin
Days:= Trunc(d);
Result.gds_quad_high:= Days + IBDateDelta;
Result.gds_quad_low:= Trunc((d - Days) * MSecsPerDay10);
end;

function QuadToDate(ibd: TISC_QUAD): TDateTime;
begin
Result:= ibd.gds_quad_high - IBDateDelta + ibd.gds_quad_low / MSecsPerDay10;
end;

function nextdate (var datn,datk: ISC_QUAD): ISC_QUAD;cdecl;
var d,m,y:Word;
r:integer;
DateFrom, DateTo, DateResult: TDateTime;
begin
DateFrom := QuadToDate(datn);
DateTo := QuadToDate(datk);
decodedate(DateFrom,y,m,d);
inc(m);
if m>12 then
begin
inc(y);
m:=1;
end;
d:=1;
DateResult:=encodedate(y,m,d)-1;
if DateResult>DateTo then
begin
r:=Trunc(DateTo);
end
else
begin
r:=Trunc(DateResult);
end;
Result := DateToQuad(r);
end;
exports
nextdate;
begin
end.

> текст IB-скрипта, c пом.которого ты объявил такую-то ф-цию
> в своей IB-базе

DECLARE EXTERNAL FUNCTION NDAT
DATE,
DATE
RETURNS DATE FREE_IT
ENTRY_POINT "nextdate" MODULE_NAME "dates"


> текст SQL-предложения, в котором фигурирует обращение к
> этой UDF-ф-ции

CREATE PROCEDURE NEW_PROCEDURE(
DN DATE,
DK DATE)
AS
DECLARE VARIABLE DS DATE;
begin
ds=ndat(dn,dk);
suspend;
end


 
Вася Добрый   (2003-12-29 15:09) [12]


> результат ф-ции - 8-байтное значение в формате IB DATE -
> вполне м.б. возвращен серверу по значению

Я бы рад по значению, но IBExpert ругается, говорит что данные такого типа передаются только по ссылке.
Мне вообще бы хоть как передать (ну и получить).


 
Digitman ©   (2003-12-29 15:10) [13]

текст UDF я привел выше

текст декларации в скрипте для ПРИВЕДЕННОЙ Паскаль-декларации и реализации UDF не долежен содержать FREE_IT (это как раз грабли, которыми ты получил по лбу)

DECLARE EXTERNAL FUNCTION NDAT
DATE,
DATE
RETURNS DATE
ENTRY_POINT "nextdate" MODULE_NAME "dates"


> CREATE PROCEDURE NEW_PROCEDURE(
> DN DATE,
> DK DATE)
> AS
> DECLARE VARIABLE DS DATE;
> begin
> ds=ndat(dn,dk);
> suspend;
> end


начерта suspend ? обоснуй...


 
Digitman ©   (2003-12-29 15:15) [14]

и еще (проглядел я явную плюху у тебя)

CREATE PROCEDURE NEW_PROCEDURE(
DN DATE,
DK DATE)
RETURNS (DS DATE) /* !!!!!!!!!!!!!!!!!! */
AS
begin
ds=ndat(dn,dk);
/* suspend; под великим сомнением необходимость саспенда здесь - нужен он только если SP используется клиентом как возвращающая НД, управляемый автом-ки создаваемым курсором на серв.стороне*/
end


 
Digitman ©   (2003-12-29 15:32) [15]


> Вася Добрый (29.12.03 15:09) [12]


ах да ! пардон) ... действительно - так

ну тады - не менее просто :

function nextdate (var datn,datk: TISC_QUAD): PISC_QUAD; cdecl;
var
Dat, DateFrom, DateTo, DateResult: TDateTime;
begin
DateFrom := QuadToDate(datn);
DateTo := QuadToDate(datk);
/////////////
decodedate(DateFrom,y,m,d);
inc(m);
if m>12 then
begin
inc(y);
m:=1;
end;
d:=1;
Dat:=encodedate(y,m,d) - 1;
if Dat > DateTo then
begin
DateResult := Trunc(DateTo);
end
else
begin
DateResult := Trunc(Dat);
end;
/////////////

Result := @datk;
Result^ := DateResult;

end;

DECLARE EXTERNAL FUNCTION NDAT
DATE,
DATE // этот форм.параметр используем для передачи факт.параметра и одновременно для возврата рез-та
RETURNS PARAMETER 2
ENTRY_POINT "nextdate" MODULE_NAME "dates"


 
Digitman ©   (2003-12-29 15:45) [16]

и , наконец, возвращаясь к твоему первонач.варианту с FREE_IT ..

он тоже работает, но применение его здесь вряд ли оправдано, если не сказать - вредно (явно излишние и бестолковые операции по перераспределению памяти) :

function nextdate (var datn,datk: TISC_QUAD): PISC_QUAD; cdecl;
var
Dat, DateFrom, DateTo, DateResult: TDateTime;
begin
DateFrom := QuadToDate(datn);
DateTo := QuadToDate(datk);
/////////////
decodedate(DateFrom,y,m,d);
inc(m);
if m>12 then
begin
inc(y);
m:=1;
end;
d:=1;
Dat:=encodedate(y,m,d) - 1;
if Dat > DateTo then
begin
DateResult := Trunc(DateTo);
end
else
begin
DateResult := Trunc(Dat);
end;
/////////////

Result := ib_util_malloc(SizeOf(Result^)); //запрос блока памяти у менеджера памяти IB по станд.соглашениям

Result^ := DateResult;//запись в него рез-та, после получения рез-та сервер сам освободит блок, ибо мы требуем от него это явно, указав FREE_IT-спецификатор рез-та

end;


DECLARE EXTERNAL FUNCTION NDAT
DATE,
DATE
RETURNS
DATE FREE_IT //всегда ожидается возврат по ссылке, вне зависимомти от типа результата, ибо реально всегда будет возвращен 4-байтный указатель на блок памяти, выделенный в теле UDF по ib_util_malloc()

ENTRY_POINT "nextdate" MODULE_NAME "dates"


 
Вася Добрый   (2003-12-29 16:31) [17]


> Result := @datk;
> Result^ := DateResult;

Ошибочка: Result^ := DateToQuad(DateResult);
УРРРРРАААААА!!!!!
ЗАРАБОТАЛА!!!
Digitman, я тебя люблю!!!!!!!
З.Ы. И откуда ты всё знаешь?!?!?


 
Digitman ©   (2003-12-29 16:42) [18]


> И откуда


знамо, откуда) ... от верблюда !)


> УРРРРРАААААА!!!!!
> ЗАРАБОТАЛА!!!


я ж тебе сразу сказал - вот тебе концептуальное решение проблемы) .. и головенкой-то ты шевели малясь))) ... не могу ж я какжную строчку свою выверять-вылизывать тут) ... оно не мне - оно тебе нада))))


 
Digitman ©   (2003-12-29 16:50) [19]

а про саспенд-то - почеши репу) ... не поленись)... вопрос не менее важный ... хоть и не шибко принципиальный с т.з. "жизнеспособности" кода ... ресурсы - они ведь не резиновые)



Страницы: 1 вся ветка

Текущий архив: 2004.01.20;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.017 c
1-63205
Ser_ega
2004-01-09 23:17
2004.01.20
Копия экрана!!!


1-63222
димка
2004-01-10 20:19
2004.01.20
как проверить запущена ли программа


3-62973
veb
2003-12-24 12:28
2004.01.20
Открытие из BLOB


14-63399
sirgfine
2003-12-28 03:19
2004.01.20
Неполадка программы


3-62972
NickNaz
2003-12-23 12:49
2004.01.20
Столбец DbGrid