OberonCore
https://forum.oberoncore.ru/

Проблема: Delphi <--> CP
https://forum.oberoncore.ru/viewtopic.php?f=5&t=5520
Страница 1 из 2

Автор:  prospero78 [ Среда, 14 Октябрь, 2015 20:37 ]
Заголовок сообщения:  Проблема: Delphi <--> CP

Есть уже готовый сервер телемеханики у нас на подстанции. Написан на Delphi 6. К нему есть библиотека в виде DLL и файл с примером её использования.
Я на КП решил сделать допил сервера -- он не может делать нужные мне вещи.
В DLL есть функции которые отрабатывают нормально:
Код:
function tmInit(ServerName, LocalName: PChar):SmallInt .... stdcall...'_tmInit@8'
function tmClose():SmallInt.... stdcall.... '_tmClose@0'


А вот при попытке передать структуру по ссылке вылетает исключение:
Код:
function tmGetAnalog(cannel, remote_technic_unit, point: SmallInt; pStatus:pTs):SmallInt....stdcall....'_tmGetAnalog@12'

Судя по кратности байтов в передаче -- все параметры передаются по 4 байта (32 бита).
Тип описанный в исходнике:
Код:
type
  TStatus = record
    Status: SmallInt;
    Field: DWORD;
  end;

  pTs = @TStatus (* возможно тут ошибся, но точно указатель на record *)


Как эту структуру описал я в КП:
Код:
TYPE
  TStatus* = RECORD
    Status*: SHORTINT;
    Field*  : CHAR;
  end;

  pTs = POINTER TO TStatus


И, короче, понятно. не катит.
Коллеги, подскажите, что я делаю не так?
Не подскажете -- пеняйте на себя. Буду плюшку рисовать на Delphi)))))

(* жуткий завал на работе, пришлось свой почин по учебнику пока приостановить *)

ADD. Есть ли у кого-то на крайний случай опыт стыковки DLL (Delphi 6) + FreePascal\Lazarus. Нет желания проприетарщину гонять.

Автор:  Илья Ермаков [ Среда, 14 Октябрь, 2015 20:54 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Почитайте в доке ББ раздел Платформенно-зависимые особенности.

Нужно RECORD, соответствующий чужим структурам, объявлять как [untagged].

Автор:  Иван Кузьмицкий [ Среда, 14 Октябрь, 2015 20:58 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Надо делать через [untagged] RECORD, на форуме много было обсуждений этого.

Автор:  prospero78 [ Среда, 14 Октябрь, 2015 21:13 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Я уже пробовал untagged. Не помогло.

Сейчас, пока ел, подумал, почему я DWORD и CHAR приравнял?

Хорошо бы где-то информации накопать по размерам типов в Delphi)

Автор:  Илья Ермаков [ Среда, 14 Октябрь, 2015 21:23 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

word - 16 бит.
DWORD, соответственно (он вообще WinApi-вский, по-моему) - 32. Как и Cardinal.

Т.е. неправильно приравняли.

Shortint сколько бит в дельфе? 16?

Автор:  prospero78 [ Среда, 14 Октябрь, 2015 21:28 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

SmallInt -- да. 16 бит. -32000....+32000.

Автор:  Роман М. [ Четверг, 15 Октябрь, 2015 01:58 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Для примера можно посмотреть исходник модуля WinApi (прокрутив до следующей секции TYPE).

Возможно вместо RECORD [untagged] нужно выставить RECORD [noalign].
Код:
IMPORT SYSTEM;

TYPE
  PChar = POINTER TO ARRAY [untagged] OF SHORTCHAR;
  DWORD = INTEGER;
  SmallInt = SHORTINT;

  TStatus* = RECORD  [noalign]
    status*: SmallInt;
    field*  : DWORD;
  end;

  pTs = POINTER TO TStatus;

А как описан интерфейс функций Дельфи в модуле КП?

Автор:  prospero78 [ Четверг, 15 Октябрь, 2015 09:26 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Ну вот пришёл на работу, попытка №2
Всё-таки вместо DWORD -- в исходнике Word.
Код:
    TADRtm = record
        Ch:    SmallInt;
        RTU:   SmallInt;
        Point: SmallInt;
    end;


    TStatusPoint = record
        Status: SmallInt;
        Flags:  Word;
    end;

  pSP          = ^TStatusPoint;



Моя структура:
Код:
   TYPE
      tAdrTm* = RECORD [untagged]  (* Адрес ТМ *)
         ch*:    SHORTINT;
         rtu*:   SHORTINT;
         point*: SHORTINT;
      END;
      
      tStatusPoint* = RECORD [untagged]
         status*: SHORTINT;
         flags*:  CHAR;
    END;

    tSp* = POINTER [untagged] TO tStatusPoint;


В итоге ругается, что не можно сделать NEW для untagged.
Что можно, я не разобрался)

Результат вызова функции из ДЛЛ:
Код:
Отключение прошло успешно
Соединение прошло успешно
tmStatusFull:
 Запрос прошёл успешно =  1
#TC10:1:16=

И окно отладки, при попытке прочитать поля структуры; окошко утверждает, что sp (который tSp*) -- NIL. Ответ чувствую, простой, но не догоняю.

Автор:  prospero78 [ Четверг, 15 Октябрь, 2015 10:14 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Попытался побаловаться с модулем SYSTEM:
Код:
   adr_SP:=SYSTEM.ADR(_SP); (* получить адрес структуры*)
   adr_pTsp:=SYSTEM.ADR(SP); (* получить адрес указателя на структууы*)
   SYSTEM.PUT(adr_pTsp, adr_SP); (* сохранить в указателе адрес структуры *)
      
   Result:=p.tmStatusFull(adr, SP);
      
   SYSTEM.GET(adr_pTsp, _SP.status);
   StdLog.String('_SP.status=');
   StdLog.Int(_SP.status);
   StdLog.Ln;
      
   SYSTEM.GET(adr_pTsp+4, _SP.flags);
   StdLog.String('_SP.flags=');
   StdLog.Int(ORD(_SP.flags));
   StdLog.Ln;

Перестал отладчик ругаться на NIL, выдал волшебный результат, возможно из-за того, что [untagged].
Результат не меняется, в не зависимости от того, что я делаю с телепараметром. Видимо, промахиваюсь с ячейкой памяти. Как бы теперь подглядеть?))) Хм.... Есть у меня ломик....

Автор:  prospero78 [ Четверг, 15 Октябрь, 2015 12:00 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Попытка прочитать значение указателя памяти [untagged] и структуры закончилась мусорным результатом.
Что меняю телесигнал, что не меняю -- одинаково, (-10...+10) байт в памяти вокруг адреса -- не меняются.
И что совсем подозрительно: адреса структуры без тега, и указателя на структуру без тэга -- разница всего 4 байта?....
Уж не идёт ли затирка данных?

АДД. Добавил в структуру 3 поля CHAR, и вижу, что размер структуры стал все 10 байт. Значит без них было всего 4. Хм. А правильно ли это? Ведь в стек кладётся все 4 байта?...

Автор:  prospero78 [ Четверг, 15 Октябрь, 2015 12:49 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Продолжение детектива.
Все поля в памяти располагаются "задом наперёд" -- чем ближе поле к началу -- тем меньше его адрес.
А адрес последнего поля совпадает с адресом структуры untagged.

Автор:  prospero78 [ Четверг, 15 Октябрь, 2015 13:06 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Вопрос знатокам: а при описании параметров процедур в интерфейсном модуле -- типы SHORTINT, INTEGER и т. д. -- ссылаются на untagged типы или как?

Автор:  prospero78 [ Четверг, 15 Октябрь, 2015 13:18 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

УРААААА!!!!
Проблема с tmStatus решена!!!!!!
Я в библиотеке параметрам подставляю untagged типы переменных SHORTINT! )))

Автор:  prospero78 [ Четверг, 15 Октябрь, 2015 13:50 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Уря)
Проблема с tmSetStatus решена))) (аналогично -- описание типов как untagged)
Пример для таких как я:
Код:
   TYPE
      tByte* = RECORD [untagged]
         val* : BYTE;
      END;

Автор:  Илья Ермаков [ Четверг, 15 Октябрь, 2015 14:31 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Послушайте, Вам POINTER TO Status, в принципе, не нужен.

Вы должны объявить на КП в сигнатуре процедуры (...., VAR pSt: Status) - это как раз эквивалентно передаче указателя.

При условии, что библиотека не запоминает нигде этот адрес и не обращается по нему после вызова.
Хотя даже в таком случае можно её будет натравить на глобальный в модуле VAR stat: Status,

Автор:  prospero78 [ Четверг, 15 Октябрь, 2015 15:54 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Ценный совет, спасибо. Сейчас попробую)
Библиотека по передаваемой ссылке записывает свои данные и на этом всё. Ей эта память не интересна.

Не могу передать в качестве аргумента пустую строку. Видимо, форматы отличаются.

(* Хотя вообще глупость написал. При вызове tmSetStatus -- ARRAY OF SHORTCHAR -- вполне прокатывает. Такая же пустая строка *)

After ADD. Указание VAR параметров работает, но возвращает почему-то (как и прежде) в tmAnalog() 3.402823466385289E+38 = MAX (SHORTREAL).

After ADD2. Ах-ха-ха-ха.... )))) tmSetAnalog() работает вполне прилично))))

After ADD3. Вот я и выяснил, что tmAnalog() как INTEGER возвращает 0. Хм. К чему бы это?...

Автор:  Роман М. [ Четверг, 15 Октябрь, 2015 17:55 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

prospero78 писал(а):
Вопрос знатокам: а при описании параметров процедур в интерфейсном модуле -- типы SHORTINT, INTEGER и т. д. -- ссылаются на untagged типы или как?

[untagged] означает инструкцию для сборщика мусора: память не резервировать, не освобождать, при указании на тип Запись обращать как к "чужой" структуре, без получения служебной информации о ней.

prospero78 писал(а):
Уря)
Проблема с tmSetStatus решена))) (аналогично -- описание типов как untagged)
Пример для таких как я:
Код:
   TYPE
      tByte* = RECORD [untagged]
         val* : BYTE;
      END;

Простые типы данных не нужно специально обворачивать в контейнеры типа Запись. Это излишне. К ним обращаются напрямую.

Можно ли взглянуть на интерфейс в КП полностью?

Автор:  prospero78 [ Четверг, 15 Октябрь, 2015 19:00 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Роман М. писал(а):
[Можно ли взглянуть на интерфейс в КП полностью?

Ахтунг.
Много букав.
Код:
MODULE AsduTmaccess ["tmaccess"];      
   
   TYPE
      
      tAdrTm* = RECORD [untagged]  (* Адрес ТМ *)
         ch*:    SHORTINT;
         rtu*:   SHORTINT;
         point*: SHORTINT;
         
      END;
      
      tStatusPoint* = RECORD [untagged]
         status*:  SHORTINT;
         flags*:  CHAR;
    END;
      
   
      tAnalogPoint* = RECORD [untagged]
        asFloat*: SHORTREAL;
        asCode*:  SHORTINT;
        Flags*:   CHAR;
        Units*:   ARRAY 10 OF SHORTCHAR;
    END;

   PROCEDURE tmInit*['_tmInit@8'](IN ServerName, LocalName:
                                                ARRAY OF SHORTCHAR): SHORTINT;

   PROCEDURE tmClose*['_tmClose@0'](): SHORTINT;
   
   PROCEDURE tmStatus*['_tmStatus@12'](Ch, RTU, Point: SHORTINT):SHORTINT;
   
   
   PROCEDURE tmSetStatus*['_tmSetStatus@24'](Ch, RTU, Point: SHORTINT;
                                          Value: BYTE;
                                          Time: ARRAY OF SHORTCHAR;
                                          Hund: SHORTINT): SHORTINT;   
                                                                                    
   PROCEDURE tmAnalog*['_tmAnalog@20'] (Ch, RTU, Point: SHORTINT;
                                                Time: ARRAY OF SHORTCHAR;
                                                RetroNum: SHORTINT):
                                                SHORTREAL;
   
   PROCEDURE tmSetAnalog*['_tmSetAnalog@20']
                                             (Ch, RTU, Point: SHORTINT;
                                             Value: SHORTREAL;
                                             Time: ARRAY OF SHORTCHAR):
                                             SHORTINT;   

                                                   
   PROCEDURE tmAnalogFull*['_tmAnalogFull@24'] (Ch, RTU, Point: SHORTINT;
                                                VAR ap: tAnalogPoint;
                                                Time: ARRAY OF SHORTCHAR;
                                                RetroNum: SHORTINT):
                                                SHORTREAL ;
                                                   
   
   PROCEDURE tmStatusFull*['_tmStatusFull@16']
                                          (Ch, RTU, Point: SHORTINT;
                                          VAR SP: tStatusPoint):SHORTINT;
         
END AsduTmaccess.


Сейчас буду пробовать упрощать.
По большому счёту, я эти типы понавводил чтобы приблизиться к оригиналу на Delphi

Что совсем неприятно -- пишу один к одному на Delphi -- всё работает, зараза такая...
Строго говоря, 5 из 6 процедур работают.
Мне нужна теперь только tmAnalog, либо tmAnalogFull.

При попытке выполнить tmAnalog вывод: tmAnalog= 3.402823466385289E+38
При попытке выполнить tmAnalogFull вылетает отладчик с милым сообщением: undefined real result (81E3, 37E)

Автор:  Alexander Shiryaev [ Четверг, 15 Октябрь, 2015 20:32 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

Цитата:
flags: CHAR

CHAR лучше заменить на SHORTINT (Delphi Word → Component Pascal SHORTINT).

Все массивы должны быть с флагом untagged (ARRAY ... OF → ARRAY [untagged] ... OF).

Скорее всего надо заменить Time: ARRAY OF SHORTCHAR → VAR Time: ARRAY [untagged] OF SHORTCHAR (как в Delphi?)

Delphi Single → Component Pascal SHORTREAL
Delphi Double → Component Pascal REAL
Типа Delphi Real в Component Pascal нет

Автор:  prospero78 [ Четверг, 15 Октябрь, 2015 21:14 ]
Заголовок сообщения:  Re: Проблема: Delphi <--> CP

В оригинале вместо char используется word.
Я не уверен, что передача флагов будет работать верно.

Массивы там вообще никак не влияют, но за совет спасибо.

У уже написал переходную DLL на Delphi и выяснил, что DLL сама не принимает из оригинальной DLL значение.
Хотя оконное приложение прекрасно получает эти значения.

Код:
VAR Time: ARRAY OF SHORTCHAR
<-- разве это не будет обращение по ссылке?

Страница 1 из 2 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/