Перевод С в Pascal
От: Аноним  
Дата: 06.01.08 17:46
Оценка:
Всем привет!
Народ, помогите, плз: есть DLL на С, пробую перевести её в Delphi,компилится без ошибок, но не работает. Может, кто поможет перевести или скажет, в чем засада?
Текст С:

_declspec(dllexport) void Highdays (double *series, double *days, long int window, long int size)

{ double *in, *out;
long int i,j;
long int highest;

in=series;
out= days;

for (i=0; i<size; i++)
{if (i < window-1)
*out=3.4e38;
else
{ highest= 0;
for (j=1; j< window; j++)
{ if (*(in-j) > *(in-highest)) highest=j; }
*out=highest;
}
in++; out++;
}

}

Текст Pascal:

library Indicator_P;
uses
SysUtils,
Classes;

{$R *.res}
type
TSeries= array of Real;
Series=^TSeries;
TDays=array of Real;
Days=^TDays;

procedure Highdays( var Series;var Days;Window:Integer;Size:Integer);stdcall;
var
Ins,Outs:Real;
Highest,i,j:Integer;
begin
Ins:=Real (Series);
Outs:=Real (Days);
for I := 0 to Size — 1 do
begin
if i<Window-1 then
Outs:=3.4e38
else
begin
Highest:=0;
for J := 1 to window do
begin
if ((Ins-j)>(Ins-Highest)) then
Highest:=j;
end;
Outs:=Highest;
end;
Ins:=Ins+1;
Outs:=Outs+1;
end;
end;
exports Highdays name 'Пример библиотеки' ;
begin
end.

Заранее спасибо!
Re: Перевод С в Pascal
От: OdesitVadim Украина  
Дата: 06.01.08 18:13
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Всем привет!

[scip]
вместо real используем double.
А>type
А>TSeries= array of Real;
А>Series=^TSeries;
А>TDays=array of Real;
А>Days=^TDays;

А>procedure Highdays( var Series;var Days;Window:Integer;Size:Integer);stdcall;

а понял, что объявил? это не Си, это делфи. тут обявлены безтиповые переменные Series и Days, а не переменные без имени и типа Series и Days
лучше уже где то так
procedure Highdays( var _series:Series;var _days:Days;Window:Integer;Size:Integer);stdcall;
А>exports Highdays name 'Пример библиотеки' ;

Зачем русские имена функции для экспорта?
лучше оставь просто так
exports Highdays;
... << RSDN@Home 1.2.0 alpha rev. 787>>
Re[2]: Перевод С в Pascal
От: Аноним  
Дата: 06.01.08 18:40
Оценка:
Здравствуйте, OdesitVadim.
Спасибо за ответ, переписал код,результат тотже.
А в объявлении процедуры пробовал использовать ссылки на массив.
Re[2]: Перевод С в Pascal
От: Аноним  
Дата: 06.01.08 18:49
Оценка:
Здравствуйте, OdesitVadim!
Я так понял, код должен быть следующим:
type
TSeries= array of Double;
Series=^TSeries;
TDays=array of Double;
Days=^TDays;

procedure Highdays( var _series:Series;var _days:Days;Window:Integer;Size:Integer);stdcall;

var
Ins,Outs:Double;
Highest,i,j:Integer;
begin
Ins:=Double (Series); {Строка 21}
Outs:=Double (Days);
for I := 0 to Size — 1 do
begin
if i<Window-1 then
Outs:=3.4e38
else
begin
Highest:=0;
for J := 1 to window do
begin
if ((Ins-j)>(Ins-Highest)) then
Highest:=j;
end;
Outs:=Highest;
end;
Ins:=Ins+1;
Outs:=Outs+1;
end; {Строка 39}
end;
exports Highdays name 'Пример библиотеки' ;
begin
end.

При компиляции выкакивают сообщения:
[Pascal Error] Indicator_P.dpr(21): E2029 '(' expected but ';' found
[Pascal Error] Indicator_P.dpr(22): E2010 Incompatible types: 'Double' and 'Series'
[Pascal Error] Indicator_P.dpr(22): E2029 '(' expected but ')' found
[Pascal Error] Indicator_P.dpr(23): E2066 Missing operator or semicolon
[Pascal Error] Indicator_P.dpr(39): E2029 ')' expected but ';' found
Re[3]: Перевод С в Pascal
От: OdesitVadim Украина  
Дата: 06.01.08 19:16
Оценка:
А> Ins:=Double (Series); {Строка 21}
Нельзя привести тип к переменной.
А> Outs:=Double (Days);
и здесь тоже.

Хотя если напишете так
Outs:=Double (_days^); — тоже не то — там же массив.
А> exports Highdays name 'Пример библиотеки' ;
а что это???

В целом, нужно собраться и аккуратно перевести код, подумав предварительно, что он делает
... << RSDN@Home 1.2.0 alpha rev. 787>>
Re[3]: Перевод С в Pascal
От: OdesitVadim Украина  
Дата: 06.01.08 19:23
Оценка:
А> Ins:=Double (Series); {Строка 21}
Нельзя привести тип к переменной.
А> Outs:=Double (Days);
и здесь тоже.

Хотя если напишете так
Outs:=Double (_days^); — тоже не то — там же массив.
А> exports Highdays name 'Пример библиотеки' ;
а что это???

В целом, нужно собраться и аккуратно перевести код, подумав предварительно, что он делает
... << RSDN@Home 1.2.0 alpha rev. 787>>
Re[4]: Перевод С в Pascal
От: SergKr  
Дата: 06.01.08 19:29
Оценка:
Здравствуйте, OdesitVadim, Вы писали:

OV>а что это???


OV>В целом, нужно собраться и аккуратно перевести код, подумав предварительно, что он делает


Это вот чего такое (только на английском)
//This indicator is very simple too except that an entire
// time series (all bars) is passed back and forth at once
// instead of a bar at a time.

// The function of the DLL is to return the number of days ago
// that the highest value in a window of the time series occurred.
// The window size is variable and if the highest value was today,
// then zero is returned.

//Note that the Trader N/A value is returned until a complete
// window occurs.

// The parameter “series” is the input array
// The parameter “days” is the output array
// The parameter “window” is the size of the lookback window
// The parameter “size” is the number of bars in the arrays

_declspec(dllexport) void Highdays (double *series, double *days, long int window, long int size)

{ double *in, *out;
long int i,j;
long int highest;

in=series; // the very first bar input
out= days; // the first bar to output

for (i=0; i<size; i++) // go thru all bars
{if (i < window-1) // see if we have a whole window yet
*out=3.4e38; // the N/A value that shows nothing on the chart
else
{ highest= 0;
for (j=1; j< window; j++) // search for highest value
{ if (*(in-j) > *(in-highest)) highest=j; }
*out=highest; // number of days ago the highest was
}
in++; out++; // go to next bar
}

}
Re: Перевод С в Pascal
От: trophim Россия  
Дата: 07.01.08 02:34
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Всем привет!

А>Народ, помогите, плз: есть DLL на С, пробую перевести её в Delphi,компилится без ошибок, но не работает. Может, кто поможет перевести или скажет, в чем засада?
А>Текст С:

Немного причешем код и припишем явно stdcall (ибо по умолчанию скорее всего cdecl):
__declspec(dllexport) __stdcall
void Highdays (double *series, double *days, long int window, long int size)
{
    double *in, *out;
    long int i,j;
    long int highest;

    in=series;
    out= days;

    for (i=0; i<size; i++)
    {
        if (i < window-1)
            *out=3.4e38;
        else
        {
            highest = 0;
            for (j=1; j< window; j++)
            {
                if (*(in-j) > *(in-highest))
                    highest=j;
            }
            *out = highest;
        }
        in++;
        out++;
    }
}


На дельфе может получиться нечно вроде такого. Код переведен строчка-в-строчку "в лоб" (лучше конечно понять что делает алгоритм и немного переделать на array of double):

library Project1;

uses
  SysUtils,
  Classes;

{$R *.res}

procedure Highdays (series:PDouble; days:PDouble; window:Longint; size:Longint); stdcall;
var _in, _out: PDouble;
    i,j:Longint;
    highest:Longint;

    function GetAt (p: PDouble; n: Integer) : Double;
    begin
        Result := PDouble( Integer(p) + n*sizeof(Double) )^;    
    end;

begin
    _in := series;
    _out := days;

    for i := 0 to size-1 do
    begin
        if (i < window-1) then
            _out^ := 3.4e38
        else
        begin
            highest := 0;
            for j := 1 to window-1 do
            begin
                if (GetAt(_in,-j) > GetAt(_in,-highest)) then
                    highest := j;
            end;
            _out^ := highest;
        end;

        inc(_in);
        inc(_out);
    end;
end;

exports Highdays;

begin
end.


Следует также обратить внимание на имя экспортированной функции в C++ проекте. Оно, скорее всего, подвергнуто mangling и выглядит совсем не как 'Highdays'. Побороть это можно при помощи def-файла.
[EOF]
Let it be! — Давайте есть пчелу!
Re[2]: Перевод С в Pascal
От: SergKr  
Дата: 07.01.08 09:35
Оценка:
Здравствуйте, trophim, Вы писали:


T>На дельфе может получиться нечно вроде такого. Код переведен строчка-в-строчку "в лоб" (лучше конечно понять что делает алгоритм и немного переделать на array of double)

Спасибо огромное, все заработало!
Это некий пример в SDK, к сожалению,очень функционально ненужный и единственный:
//This indicator is very simple too except that an entire
// time series (all bars) is passed back and forth at once
// instead of a bar at a time.

// The function of the DLL is to return the number of days ago
// that the highest value in a window of the time series occurred.
// The window size is variable and if the highest value was today,
// then zero is returned.

//Note that the Trader N/A value is returned until a complete
// window occurs.

// The parameter “series” is the input array
// The parameter “days” is the output array
// The parameter “window” is the size of the lookback window
// The parameter “size” is the number of bars in the arrays

_declspec(dllexport) void Highdays (double *series, double *days, long int window, long int size)

{ double *in, *out;
long int i,j;
long int highest;

in=series; // the very first bar input
out= days; // the first bar to output

for (i=0; i<size; i++) // go thru all bars
{if (i < window-1) // see if we have a whole window yet
*out=3.4e38; // the N/A value that shows nothing on the chart
else
{ highest= 0;
for (j=1; j< window; j++) // search for highest value
{ if (*(in-j) > *(in-highest)) highest=j; }
*out=highest; // number of days ago the highest was
}
in++; out++; // go to next bar
}

}

Эта конструкция фактически возвращает число дней, прошедших с момента наступления локального максимума в числовом ряду ( потоке биржевых котировок).
Если не сложно, было бы интересно посмотреть на вариант с array of double.
Еще раз огромное спасибо, сейчас буду разбираться в Вашем коде.
Re[3]: Перевод С в Pascal
От: trophim Россия  
Дата: 08.01.08 06:37
Оценка:
Здравствуйте, SergKr, Вы писали:

SK>Эта конструкция фактически возвращает число дней, прошедших с момента наступления локального максимума в числовом ряду ( потоке биржевых котировок).

SK>Если не сложно, было бы интересно посмотреть на вариант с array of double.
SK>Еще раз огромное спасибо, сейчас буду разбираться в Вашем коде.

А чего там разбираться — это полный аналог кода на Си. Только вот функция GetAt — это есть очень неоптимально, потому что для простого получения элемента вызывается целая функция, в то время как в Сишном кода всего лишь идет получение элемента массива. Хотя, если эта функция совсем некритична по времени выполнения, то и фиг с ней, пусть будет так — время, которое уйдет на вылизывание, дороже.
[EOF]
Let it be! — Давайте есть пчелу!
Re[4]: Перевод С в Pascal
От: Аноним  
Дата: 14.01.08 10:46
Оценка:
T>А чего там разбираться — это полный аналог кода на Си. Только вот функция GetAt — это есть очень неоптимально, потому что для простого получения элемента вызывается целая функция, в то время как в Сишном кода всего лишь идет получение элемента массива. Хотя, если эта функция совсем некритична по времени выполнения, то и фиг с ней, пусть будет так — время, которое уйдет на вылизывание, дороже.
GetAt(_in,-j) можно заменить на inc(_in,-j), если включён расширенный синтаксис и скорость при этом будет большая
Re: Перевод С в Pascal
От: OCTAGRAM Россия http://octagram.name/
Дата: 24.01.08 10:50
Оценка:
Аноним 393 пишет:


> Всем привет!

> Текст С:

> _declspec(dllexport) void Highdays (double *series, double *days, long

> int window, long int size)

> Текст Pascal:


> TSeries= array of Real;

> Series=^TSeries;
> TDays=array of Real;
> Days=^TDays;
>
> procedure Highdays( var Series;var
> Days;Window:Integer;Size:Integer);stdcall;

> Заранее спасибо!


Никто не обратил внимания на конструкцию "array of ..."
Дело в том, что в Delphi array[...] of ... — это просто массив.
А array of ... — это уже динамический массив. То есть, в переменной
этого типа хранится указатель. Прямо по адресу, на который указывает
этот указатель, будут элементы массива подряд. А по отрицательным
смещениям -4 и -8 будут количество элементов и счётчик ссылок.

Как минимум, не надо делать указатель на указатель. А в идеале и вовсе
отказаться от конструкции array of во внешних вызовах.

Я предлагаю сделать в Delphi–описании типом параметра указатель на Double:

procedure Highdays_Raw(Series : PDouble;
var Days : Double; Window : Integer; Size : Integer); stdcall;

и тут же обёртку:
function Highdays(const Series : array of Double; Window : Integer) :
array of Double;
begin
SetLength(Result, Length(Series));
Highdays_Raw(@(Series[0]), Result[0], Window, Length(Series));
end;

в качестве чернового варианта. В данном случае, заметьте, опять
конструкция "array of", но на этот раз она означает open array для
Series. Open Array может быть только типом аргумента. В любом другом
месте array of значит динамический массив. Вот и результат здесь будет
динамическим массивом. Если нужен динамический массив в качестве типа
аргумента, нужно сначала объявить такой тип, а потом это имя
использовать как тип параметра. В Delphi предпочтительнее использовать
Open Array, так как для таких процедур можно использовать
вызовы с агрегатами типа D := Highdays([1.0, 2.0, 3.0], 2); или я уж не
знаю, как её там вызывать. Кроме того, в качестве актуального типа
параметра для open array подойдёт как обычный массив, так и
динамический, ну и открытый тоже, конечно.

--
ISO/IEC 8652:1995/Amd 1:2007
Posted via RSDN NNTP Server 2.1 beta
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.