Текущий архив: 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