powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / money и currency
5 сообщений из 5, страница 1 из 1
money и currency
    #32054156
fima
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Написал я extended proc на дельфи. Все работает за исключением одного, неправильно понимается тип money. По хелпу, тип соответствующий money есть currency, хранятся оба в 8 байтах да и диапозон одинаковый.
функция в dll следующая:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
function test (Srv : Pointer) :Currency; cdecl; export;
var InputTransactionFile : TextFile;
  Typ, MaxLen, Len: Integer;
  IsNull: boolean;
  ptrMoney : Pointer;
  Money : Currency;
begin
  GetMem (ptrID_test,  8 );
  srv_paraminfo(Srv,  1 , Typ, MaxLen, Len, ptrMoney, IsNull);
  MoveMemory(pointer(Money), ptrMoney, Len);
  AssignFile (InputTransactionFile, 'c:\test.txt');
  Append (InputTransactionFile);
  Write (InputTransactionFile, FloatToStr(Money));
  CloseFile (InputTransactionFile);
  Result :=  0 ;
  FreeMem(ptrMoney);
end;

Так вот например передаю я 2,365 а получаю 10157597655,04. Еще мне непонятно почему MaxLen = 4 а Len = 8.
Что я сделал неправильно?
...
Рейтинг: 0 / 0
money и currency
    #32054168
Фотография ziktuw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вызывает подозрение вот это строчка:
MoveMemory(pointer(Money), ptrMoney, Len);
точнее выражение "pointer(Money)".
Есть уверенность, что это будет проинтерпретировано как указатель на область, где лежит значение Money? Если не ошибаюсь, такая запись всего лишь означает преобразовать то, что в скобках к виду указателя, что в данном случае означает преобразовать денежное значение в 32-разрядному адресу.
Наверно, здесь стоит сделать что-то наподобие
MoveMemory(@Money, ptrMoney, Len);

А еще лучше использовать дельфовую функцию Move. Там уже без указателей.

И еще. extended proc предполагает, что возращаемое значение имеет тип Integer и ничего другого. Через него возвращается статус исполнения. У тебя указан Currency, что неверно. Хотя к ошибке это вряд ли приведет.
...
Рейтинг: 0 / 0
money и currency
    #32054174
fima
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, небольшие неточности в приведенном коде есть, прошу прощения. Вот код с изменениями:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
function test (Srv : Pointer) :Integer; cdecl; export;
var InputTransactionFile : TextFile;
  Typ, MaxLen, Len: Integer;
  IsNull: boolean;
  ptrMoney : Pointer;
  Money : Currency;
begin
  GetMem (ptrMoney,  8 );
  srv_paraminfo(Srv,  1 , Typ, MaxLen, Len, ptrMoney, IsNull);
  MoveMemory(@Money, ptrMoney, Len);
  AssignFile (InputTransactionFile, 'c:\test.txt');
  Append (InputTransactionFile);
  WriteLn (InputTransactionFile, FloatToStr(Money));
  CloseFile (InputTransactionFile);
  Result :=  0 ;
  FreeMem(ptrMoney);
end;

Но он тоже не работает, хотя возвращает уже 11317238824,96 вместо 2,365... Непонимаю, что неправильно!
...
Рейтинг: 0 / 0
money и currency
    #32054294
Фотография ziktuw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вероятно, теперь имеет значение то обстоятельство, что Currency в Delphi - это число с плавающей точкой, а money - BCD-значение. И их, вероятно, так просто приравнять нельзя, так как в памяти представление у них разное. Поищи функцию преобразования BCD-значений в double или float. Или поэкспериметируй сам, например, смаппировав 8 байт типа money в 2 по 4 байта типа int с последующими вычислениями из этих 2-х целых значений. Как только будет получен результат таких вычислений равный заданному значению money, этот результат можно будет присвоить типу Currency.

Функцию преобразования money -> currency можно подглядеть в исходниках TCurrencyField. Там это корректно преобразуется.
...
Рейтинг: 0 / 0
money и currency
    #32054328
fima
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я попробовал проверить, там ли и то ли я читаю, включил выходной параметр, в который напрямую передаю входной. Выходной стал равен входному, т.е. читаю оттуда и то что надо. Но, попробовал использовать функцию BCDToCurr и тоже получил ошибку. Т.е. в случае неудачи использования BCDToCurr я пишу "неправильно", и именно это значение я и получил . Т.е. я так понимаю что, Делфи не воспринимает те восемь байт как TBCD. Код следующий:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
function test (Srv : Pointer) :Integer; cdecl; export;
var InputTransactionFile : TextFile;
  Typ, MaxLen, Len: Integer;
  IsNull: boolean;
  ptrMoney : Pointer;
  bcdMoney : TBcd;
  Money : Currency;
begin
  GetMem (ptrMoney,  8 );
  srv_paraminfo(Srv,  1 , Typ, MaxLen, Len, ptrMoney, IsNull);
  srv_paramset (Srv,  2 , ptrMoney,  8 );
  MoveMemory(@bcdMoney, ptrMoney,  8 );
  AssignFile (InputTransactionFile, 'c:\test.txt');
  Append (InputTransactionFile);
  if BCDToCurr(bcdMoney, Money) then
    WriteLn (InputTransactionFile, FloatToStr(Money))
  else
    WriteLn (InputTransactionFile, 'неправильно');
  CloseFile (InputTransactionFile);
  Result :=  0 ;
  FreeMem(ptrMoney);
end;
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / money и currency
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]