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

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

Общий ресурс из dll для 2х процессов. Проблема !!! [D7, Win2k]


UnDISCOvery ©   (2002-11-19 16:31:00) 

есть вот такая структура:
type
PGlobalDLLData = ^TGlobalDLLData;
TGlobalDLLData = record
S: String[50];
I: Integer;
M: TMemoryStream;
end;
Она общая для двух процессов, грузится из длл-ки. За основу взят пример из Пачеко.
----------------------------------
в длл:
GlobalData^.M := TMemoryStream.Create;
Path:=GetCurrentDir+"\BMP\111.bmp";
GlobalData^.M.LoadFromFile(Path);
-----------------------------------
в App1.exe

procedure TMainForm.LoadNextBmp;
begin
lbCount.Caption:= IntToStr(ImgCount);
try
GetDLLData(GlobalData);
GlobalData^.I:= ImgCount;
GlobalData^.M.Position:=0;
BmpArr[ImgCount].SaveToStream(GlobalData^.M);
except
ShowMessage(SysErrorMessage(GetLastError));
end;
inc(ImgCount);
if ImgCount > 3 then ImgCount:=0;
end;
---------------------------------------
в App2.exe

procedure TMainForm.btnGetGlobalDataClick(Sender: TObject);
var
Size: integer;
begin
try
GetDllData(GlobalData);
lblGlobDataStr.Caption := GlobalData^.S;
lblGlobDataInt.Caption := IntToStr(GlobalData^.I);
GlobalData^.M.Position:=0;
Image1.Picture.Bitmap.LoadFromStream(GlobalData^.M);
except
ShowMessage(SysErrorMessage(GetLastError));
end;
end;
-----------------------------------

Как видно, первое приложение циклически меняет данные общего ресурса. Второе приложение должно воспринять эти изменения.
Проблема: второе приложение не видит новые картинки из BmpArr.
В чем проблема ? Как правильно их передать ?


reonid   (2002-11-19 19:19:00) [1]

Лучше направить поток прямиком в расшаренную память:

(если копировать - уж слишком много копий возникает -
одна в самом битмапе, другая в мемористриме, третья -
в файлмаппинге - и так в обоих приложениях)

PGlobalDLLData = ^TGlobalDLLData;
TGlobalDLLData = record
S: String[50];
I: Integer;
//...
StreamDataBeginning: Integer; // сюда и далее будет писать поток
end;

//-------------------------------------------------
type
TFixedMemoryStream = class(TCustomMemoryStream)
public
constructor Create(Ptr: Pointer; Size: Longint);
function Write(const Buffer; Count: Longint): Longint; override;
end;

constructor TFixedMemoryStream.Create(Ptr: Pointer; Size: Integer);
begin
SetPointer(Ptr, Size);
end;

function TFixedMemoryStream.Write(const Buffer; Count: Longint): Longint;
var
Pos: Longint;
begin
if (Position >= 0) and (Count >= 0) then
begin
Pos := Position + Count;
if Pos > 0 then
begin
if Pos > Size then raise EStreamError.CreateFmt("%s: overflow", [ClassName]);

System.Move(Buffer, Pointer(Longint(Memory) + Position)^, Count);
Position := Pos;
Result := Count;
Exit;
end;
end;
Result := 0;
end;
//-----------------------------------------------

// при чтении или записи битмапа в поток нужно
// этот поток создавать динамически:

GetDllData(GlobalData);
Stream := TFixedMemoryStream.Create(@GlobalData^.SteamDataBeginning,
SizeOfFileMapping // размер FileMapping"a - я не знаю, чему он у тебя равен
// Но он должен быть достаточен для
// вмещения твоих битмапов.

- SizeOf(TGlobalDLLData) );

try
Stream.Position := 0;

BmpArr[ImgCount].SaveToStream(Stream);

// пишешь/читаешь из потока - поток пишет напрямую в
// расшаренный регион
...
finally
Stream.Free;
end;

Тут возникает уже вопрос синхронизации - как одно приложение узнает, что другое записало данные и пора их читать.
- нужно, вероятно, использовать мютекс + WaitForSingleObject.

PS Я не понял - тебе нужно в течение работы
менять содержимоебитмапов,
так чтобы другое приложение отслеживало эти изменения,
или же нужно выбирать из уже существующих битмапов, не меняя
их изображения?


MBo   (2002-11-19 17:14:00) [2]

при создании объекта приведенным тобой образом в общей памяти лежит указатель на объект, а сами данные - в адресном пространстве кладущего процесса.
Создав TMemoryStream и записав в него битмап, получи указатель на данные через MemoryStream.Memory, и скопируй Move MS.Size байт в общую память. В принимающей программе сделай MS.Size=нужному размеру (значение которого тоже надо держать в общей памяти) и Move из shared памяти в адрес MemoryStream.Memory


UnDISCOvery   (2002-11-19 17:07:00) [3]

> MBo
1. что значит "сырые данные" ?
2. каков механизм "копирования куска памяти" ?


UnDISCOvery   (2002-11-19 16:46:00) [4]

А при чем здесь это ?
Не понял вопроса ... :-/
в принципе - можно и не грузить по умолчанию картинку, все равно ничего не измениться ...


MBo   (2002-11-19 16:45:00) [5]

да не TMemoryStream надо в общей памяти держать, а сырые данные, а вот MemoryStream.Memory надо заставить на этот адрес указывать
(SetPointer), а надежнее, IMHO, копировать кусок памяти


Skier   (2002-11-19 16:37:00) [6]

>UnDISCOvery
GlobalData^.M := TMemoryStream.Create;
Path:=GetCurrentDir+"\BMP\111.bmp";
GlobalData^.M.LoadFromFile(Path);

А путь случаем не один и тот же ?


Наверх

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