Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Прямой доступ в память


Автор: Micher 5.10.2008, 13:55
Привет всем! Такой вопрос:
Можно ли в делфи - работать с памятью на прямую? Мне нужно написать DLL, посредством которой 2 программы связывались бы(Они не на делфи).  Например одна программа чтото пишет в определённый участок памяти, другая читает и в зависимости от того, что туда записала первая, совершает определённые действия. Версия с "общением" программ посредством файла приводить не стоит, так как очень(!) важна скорость работы.

Покопав предварительно в инете, нашёл 1 более менее интересную ссылку на форум по той же теме, но честно говоря, просто напросто запутался. http://forum.shelek.ru/index.php/topic,7579.0.html

Может, кто-нибудь знает, как лучше сделать или даже имел опыт в написании подобного кода...
Заранее спасибо

Автор: Alexeis 5.10.2008, 14:08
Micher, Да по ссылке как раз то что нужно. 
Еще можно при помощи WriteProcessMemory. Предварительно открыв при помощи OpenProcess.
Поищите в разделе "Delphi: WinAPI и системное программирование"

Автор: ne0n 5.10.2008, 14:22
Micher, никто тебе не даст рабоать с памятью напрямую....да и не нужно это)

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

сообщения:http://www.delphisources.ru/pages/faq/base/wm_cd_link.html
MMF ( демо от Rousе_): http://rouse.drkb.ru/winapi.php#mmf

Добавлено @ 14:26
Цитата(Alexeis @  5.10.2008,  14:08 Найти цитируемый пост)
Еще можно при помощи WriteProcessMemory. Предварительно открыв при помощи OpenProcess.

Alexeis,  а поделись информацией, как ?!smile проблема не в том как писать и читать, просто не могу так сходу сообразить - как найти область памяти, которая ненужна процессу и которая не  привед к ошибке?! (хоят вот только что придумал - можно создать какойнито пустой массив, вставить перед ним сигнатуру, искать в памяти ее, а потом писать...правда тут опять же жестко привязаны к размеру буфера-хз не згнаю такое будет рабоать или нет smile )

Автор: Alexeis 5.10.2008, 14:41
ne0n, Все правильно выделил участок памяти, передал его адрес процессу, который должен в него записать, и тот в свою очередь запишет в него.

Добавлено через 49 секунд
Нужно будет еще семафоров сделать, чтобы синхронизировать доступ к общей памяти

Автор: Micher 5.10.2008, 21:13
Цитата(Alexeis @ 5.10.2008,  14:08)
Micher, Да по ссылке как раз то что нужно. 
Еще можно при помощи WriteProcessMemory. Предварительно открыв при помощи OpenProcess.
Поищите в разделе "Delphi: WinAPI и системное программирование"

А что конкретно то, что нужно? smile Там много всего, не знаешь за что и взяться. Я так понял, нужно использовать FileMapping, но не получается ли это тем же самым, что обмен данными через файл? Будет ли предлагаемый вариант быстрее работы через файл?

Автор: Micher 5.10.2008, 21:29
Цитата(ne0n @ 5.10.2008,  14:22)
если количество передаваеммых данных невилико - то можно воспользоваться сообщениями(там размер буфера ограничен, точно не помню сколько) или как уже писали на форуме, на который ты дал ссылку воспользоваться можно MMF.

сообщения:http://www.delphisources.ru/pages/faq/base/wm_cd_link.html
MMF ( демо от Rousе_): http://rouse.drkb.ru/winapi.php#mmf

http://rouse.drkb.ru/winapi.php#mmf - к сожалению, нерабочая ссылка.
По поводу сообщений написано следующее: "Есть одно условие -  приложение должно содержать окно". Моё приложение содержит окно(т.е. не просто висит где-то в памяти и чото тихо делает smile ), значит по видимому с этим проблем быть не должно. Ещё такой вопрос: дело в том, что мне нужно передавать очень небольшой объём информации между программами(может байт 10-20), но при этом довольно часто(5 раз в секунду). Там переполнение какое-нибудь не может случиться?

В общем, я что-то совсем запутался smile К сожалению, в Делфи не очень разбираюсь, а в тонкостях тем более. Что всё таки посоветуете из FileMapping и сообщений?

Автор: Alexeis 5.10.2008, 21:43
Цитата(Micher @  5.10.2008,  20:29 Найти цитируемый пост)
Ещё такой вопрос: дело в том, что мне нужно передавать очень небольшой объём информации между программами(может байт 10-20), но при этом довольно часто(5 раз в секунду). Там переполнение какое-нибудь не может случиться?

  А насколько важен момент передачи? С какой точностью требуется синхронизация приложений. Для таких простых целей думаю хватит простого и стандартного механизма WM_COPYDATA

Автор: Micher 5.10.2008, 21:55
Цитата(Alexeis @ 5.10.2008,  21:43)
Цитата(Micher @  5.10.2008,  20:29 Найти цитируемый пост)
Ещё такой вопрос: дело в том, что мне нужно передавать очень небольшой объём информации между программами(может байт 10-20), но при этом довольно часто(5 раз в секунду). Там переполнение какое-нибудь не может случиться?

  А насколько важен момент передачи? С какой точностью требуется синхронизация приложений. Для таких простых целей думаю хватит простого и стандартного механизма WM_COPYDATA

2 приложения получают данные извне. Эти данные могут приходить очень по-разному: от нескольких раз в секунду до 1 раза в 3-5 секунд. Получив данные, 1 приложение должно обработать их и отослать информацию 2-му приложению(и наоборот)... по мере получения данных извне(т.е. если данные не поступают, то приложение не делает ничего).

Автор: Micher 6.10.2008, 14:33
С отправлением сообщений вроде разобрался, делаю так примерно:
Код

Function SendMes(): integer; export; stdcall;
var
  pril: hWnd;
  aCopyData: TCopyDataStruct;
 begin
   with aCopyData do
    begin
     dwData := 0;
     cbData := StrLen(PChar('Ot ulibki stanet vsem svetley!')) + 1;
     lpData := PChar('Ot ulibki stanet vsem svetley!')
    end;

   pril:= FindWindow(nil, 'ЗАГОЛОВОК ПРИЛОЖЕНИЯ, К-МУ ОТСЛЫАЕСТЯ СООБЩЕНИЕ');
   if pril <> 0 then
    begin
      SendMessage(pril, WM_COPYDATA, 0, Longint(@aCopyData));
      SendMes:=1;
    end else SendMes:=0;
 end;


Теперь не понятно, как ПРИНЯТЬ из другого приложения то, что посылает ему первое :-(
Нашёл такой примерно кусочек кода:
Код

...
type
   TForm1 = class(TForm)
     private
     procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;
   public
   end;

procedure TForm1.WMCopyData(var Msg: TWMCopyData);
 var
   sText: array[0..99] of Char;
 begin
   // generate text from parameter
  StrLCopy(sText, Msg.CopyDataStruct.lpData, Msg.CopyDataStruct.cbData);
   // write received text
  ShowMessage(sText);
 end;
...


Но мне нужна функция(она не должна быть методом какого-либо класса), которая просто вернёт строку - которую посылается 1-м приложением...

Автор: Alexeis 6.10.2008, 16:33
Цитата(Micher @  6.10.2008,  13:33 Найти цитируемый пост)
Но мне нужна функция(она не должна быть методом какого-либо класса), которая просто вернёт строку - которую посылается 1-м приложением... 

  Добавь в case функции главного окна WM_COPYDATA и напиши обработку.

Автор: Micher 6.10.2008, 16:38
Цитата(Alexeis @ 6.10.2008,  16:33)
Цитата(Micher @  6.10.2008,  13:33 Найти цитируемый пост)
Но мне нужна функция(она не должна быть методом какого-либо класса), которая просто вернёт строку - которую посылается 1-м приложением... 

  Добавь в case функции главного окна WM_COPYDATA и напиши обработку.

Честно говоря не очень понял вашу мысль smile А вообще код, который я привёл верный?

Автор: Alexeis 7.10.2008, 18:17
Цитата(Micher @  6.10.2008,  15:38 Найти цитируемый пост)
 А вообще код, который я привёл верный? 

  На вид правильный. 

Цитата(Micher @  6.10.2008,  15:38 Найти цитируемый пост)
Честно говоря не очень понял вашу мысль 

Если модуль написан на WinApi то должна быть главная функция обработчик сообщений в ней и будет происходить обработка.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)