Всем привет!
Народ, помогите, плз: есть 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.
Здравствуйте, <Аноним>, Вы писали:
А>Всем привет!
[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
Здравствуйте, 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
}
Здравствуйте, <Аноним>, Вы писали:
А>Всем привет! А>Народ, помогите, плз: есть 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-файла.
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.
Еще раз огромное спасибо, сейчас буду разбираться в Вашем коде.
Здравствуйте, 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), если включён расширенный синтаксис и скорость при этом будет большая
> Всем привет! > Текст С:
> _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 подойдёт как обычный массив, так и
динамический, ну и открытый тоже, конечно.