Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Особенности при работе с com портом в dll. [WinXP]


Дмитрий Белькевич ©   (2009-07-13 21:04:00) 

Использую компоненту TSerialPort для работы с com портами.

Метод чтения данных из порта:


function THSerialPort.Read(var Buffer; Count: Integer): Integer;
var
Overlapped: TOverlapped;
BytesRead: DWORD;
begin
FillChar(Overlapped,SizeOf(Overlapped),0);
Overlapped.hEvent:=CreateEvent(nil,False,False,nil);
ReadFile(ComHandle,Buffer,Count,BytesRead,@Overlapped);
WaitForSingleObject(Overlapped.hEvent,INFINITE);
if not GetOverlappedResult(ComHandle,Overlapped,BytesRead,False) then DoOnError('Unable to read from port',GetLastError);
CloseHandle(Overlapped.hEvent);
Result:=BytesRead;
end;


Создаю компоненту в рантайме. При создании её в OnCreate тестовой формы всё нормально работает. Данные читаются из порта без особенностей.
Когда же создаю компоненту в dll, то данные из порта не читаются.


Дмитрий Белькевич   (2009-07-14 02:02:00) [1]

>Неужто так трудно не использовать компоненты, тем более сторонние, для работы с Com-портами?

Отвязал от VCL, убрал Synchronize. Вроде всё работает.

>Если хочешь могу выслать тебе книгу П. Агурова по работе с сом-портом. Прочитаешь, поможет.

Спасибо, если проблемы продолжатся - обращусь.

Всем спасибо за участие...


Германн   (2009-07-14 01:37:00) [2]


> тем более сторонние,

Ну я сказал!
:)
P.S. Автору.
Если хочешь могу выслать тебе книгу П. Агурова по работе с сом-портом. Прочитаешь, поможет.


Германн   (2009-07-14 01:03:00) [3]


> Особенности при работе с com портом в dll. [WinXP]
>
> Дмитрий Белькевич   (13.07.09 21:04)
>
> Использую компоненту TSerialPort для работы с com портами.
>
>

Неужто так трудно не использовать компоненты, тем более сторонние, для работы с Com-портами? Тогда и не будет проблем с dll.
Вот как глянешь на Synchronize в приведённом коде, так сразу и понимаешь всю бредовость такого решения.


Loginov Dmitry   (2009-07-13 23:59:00) [4]


> При создании компоненты в VCL всё нормально работает. При
> создании из dll не срабатывает Synchronize(DoEvents). Тред
> заходит в Synchronize и DoEvents не вызывается.


Проблема из-за того, что для объекта Application, созданного в DLL, не устанавливается свойство Handle. Соответственно его нужно передавать при инициализации библиотеки. Лучше использовать пакеты. Или же другую библиотеку для работы с COM-портами, не завязанную так жестко на VCL.


Игорь Шевченко   (2009-07-13 23:59:00) [5]

Дмитрий Белькевич   (13.07.09 23:21) [3]

А обязательно DLL ? BPL не спасет ?

Может быть (точно не уверен), что Syncronize использует глобальные переменные, которые разные для DLL и для приложения. По крайней мере в classes.pas таких глобальных переменных есть.


> Есть мысль вообще синхронизацию убрать, т.к. VCL в длл не
> используется, попробовал без неё - работает, не знаю только,
>  насколько это надёжно.


все зависит от того, что находится в DoEvents и в контексте какого потока эти DoEvents должны выполняться.


Сергей М.   (2009-07-13 23:26:00) [6]


> Как синхронизацию сделать ..? Есть мысль
> вообще синхронизацию убрать


Ты уж определись как-нибудь - то ли "сделать", то ли "убрать" ..
А потом уж будем рассуждать про "в dll" и про "не в dll".


Дмитрий Белькевич   (2009-07-13 23:21:00) [7]

>в этом коде зависимостей от DLL не видно :)

Ну там кода-то моего и нет почти - компонента просто создаётся и там и там:


FHSerialPort := THSerialPort.Create(nil);
FHSerialPort.OnRxChar := ReceiveByte;
FHSerialPort.OnError := PortError;



> У тебя ошибка в 17-й строке.


Согласен, по этим данным - гадание по гуще.
Отладчиком компоненту немного пощупал. Есть новые данные...

Кроме методов чтения/записи и прочей обвязки, в компоненте создаётся тред, который обрабатывает события порта.

Вот его execute:


procedure TComThread.Execute;
var
EventHandles: Array[0..1] of THandle;
Overlapped: TOverlapped;
dwSignaled, BytesTrans: DWORD;
begin
FillChar(Overlapped,SizeOf(Overlapped),0);
Overlapped.hEvent:=CreateEvent(nil,True,True,nil);
EventHandles[0]:=StopEvent;
EventHandles[1]:=Overlapped.hEvent;
repeat
  WaitCommEvent(Owner.ComHandle,Mask,@Overlapped);
  dwSignaled:=WaitForMultipleObjects(2,@EventHandles,False,INFINITE);
  case dwSignaled of
    WAIT_OBJECT_0:Break;
    WAIT_OBJECT_0+1: if GetOverlappedResult(Owner.ComHandle,Overlapped,BytesTrans,False) then Synchronize(DoEvents);
    else Break;
  end;
until False;
Owner.PurgeIn;
Owner.PurgeOut;
CloseHandle(Overlapped.hEvent);
CloseHandle(StopEvent);
end;


При создании компоненты в VCL всё нормально работает. При создании из dll не срабатывает Synchronize(DoEvents). Тред заходит в Synchronize и DoEvents не вызывается.

Как синхронизацию сделать в случае работы в dll? Есть мысль вообще синхронизацию убрать, т.к. VCL в длл не используется, попробовал без неё - работает, не знаю только, насколько это надёжно.


Сергей М.   (2009-07-13 21:52:00) [8]

У тебя ошибка в 17-й строке.


Игорь Шевченко   (2009-07-13 21:06:00) [9]

в этом коде зависимостей от DLL не видно :)


Наверх

Титульная страница Поиск, карта сайта Написать письмо