На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> MapViewOfFile и MoveMemory порядок взаимодействия
    Изучаю возможность обращения к данным из другого приложения DELPHI.
    И в связи с этим вопросы, почему:
    1. при считывании блока до 400 байт получается получит данные только первую 1/4 из всего блока?
    2. присчитывании блока более 400 байт только 100 не зависимо от размера?
    3. почему после UnmapViewOfFile(lpBaseAddress) ни дискриптор ни адрес получить невозможно, хотя во всех примерах перед обращением из другого приложения блоки надо закрыть?
    Сообщение отредактировано: Ivan123 -
      Цитата Ivan123 @
      1. при считывании блока до 400 байт получается получит данные только первую 1/4 из всего блока?
      2. присчитывании блока более 400 байт только 100 не зависимо от размера?

      Пример кода. где то явно логическая ошибка. должно все работать.

      Цитата Ivan123 @
      3. почему после UnmapViewOfFile(lpBaseAddress) ни дискриптор ни адрес получить невозможно, хотя во всех примерах перед обращением из другого приложения блоки надо закрыть?

      UnmapViewOfFile нужно вызвать если тебе блок уже не нужен. можешь спокойно CreateFileMapping\MapViewOfFile во всех программах когда тебе нужно и закрывать когда тебе нужно. память полностью освободится если ты закроешь последний хендл.
      пс. главное не создать его в монопольном режиме (тогда только один процесс и сможет им воспользоватся)
        Цитата ViktorXP @
        UnmapViewOfFile нужно вызвать если тебе блок уже не нужен.

        Конечно это логично, возможно я сам не до конца в этом разобрался)
        Что касается первых двух пунктов, вроде интуитивно решил проблему, но понять или найти описание почему именно так поступать нужно не нашёл
        если я открываю блок виртуальной памяти из того же приложения (форма), где этот блок и создан, то функция должна выглядеть так:

        MoveMemory(lpBaseAddress, @Vdata , SizeBufIn);

        а если из другого приложения и из консоли то она уже должна быть выглядеть так:

        ..................................... SizeBufIn*4); ????
        Сообщение отредактировано: Ivan123 -
          сложно понять что ты имеешь ввиду без кода.
          Цитата Ivan123 @
          а если из другого приложения и из консоли то она уже должна быть выглядеть так:

          Тебе файл-мапинг нужен для обмена данными между приложениями?
          "SizeBufIn*4" что это? откуда это берется? ты хочешь передавать данные из нескольких программ по одной объекту "файл мапинга"? не проще ли создать несколько. для каждой операции свой. или сделать очередь за счет семафора
            Цитата ViktorXP @
            сложно понять что ты имеешь ввиду без кода


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

            Цитата ViktorXP @
            "SizeBufIn*4" что это?


            Вот код третьего приложения


            ExpandedWrap disabled
              unit U6_1;
               
              interface
               
              uses
                Windows, Math, Messages, Classes, Forms, MMSystem;
              procedure Execute;
              const
                  discret = 8000;
                  SizeBufOut = 400;
                  MMFName: pAnsiChar = 'MP';
                  a=0;
               
              type
                TForm1 = class(TForm)
                  procedure FormCreate(Sender: TObject);
                public
                  procedure WCard;
                end;
               
              var
                  hMapFile:THandle;
                  lpBaseAddress:PChar;
                  Vdata: array [0..SizeBufOut-1] of integer;
               
                  Form1: TForm1;
                  WaveFormatEx: TWaveFormatEx;
                  WaveOut:HWAVEOUT;
                  hEvent: THandle;
                  woh: WAVEHDR;
                  BufHead: TWaveHdr;
                  n: word;
               
              implementation
               
              {$R *.dfm}
               
              procedure TForm1.FormCreate(Sender: TObject);
              begin
                  WCard;
                  Execute;
              end;
               
              procedure TForm1.WCard;
              var
                BufLen: word;
                n: word;
               
                begin
                  with WaveFormatEx do
                  begin
                    wFormatTag := WAVE_FORMAT_PCM;
                    nChannels := 1;
                    nSamplesPerSec := discret;
                    wBitsPerSample := 16;
                    nBlockAlign := nChannels * (wBitsPerSample div 8);
                  end;
               
                  hMapFile := OpenFileMapping(FILE_MAP_ALL_ACCESS,False,MMFName);
                  lpBaseAddress := MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 1);
               
                  hEvent := CreateEvent(nil, false, false, nil);
                  WaveOutOpen(Addr(WaveOut), 0, addr(WaveFormatEx), hEvent, 0,CALLBACK_EVENT);
                  waveOutPrepareHeader(WaveOut, addr(woh),SizeOf(woh));
                  BufLen := WaveFormatEx.nBlockAlign * SizeBufOut;
                  with BufHead do
                    begin
                      woh.lpData := addr(Vdata);
                      woh.dwBufferLength := BufLen;
                    end;
                end;
               
              procedure Execute;
                begin
                  while a<1 do
                    begin;
                      CopyMemory(addr(Vdata), lpBaseAddress, SizeBufOut*4);/здесь получаем данные из второго приложения (почему всё таки *4?)
                      waveOutWrite(WaveOut, addr(woh), SizeOf(woh));
                      waveOutReset(WaveOut);
                    end;
                end;
               
               
              end.
              Цитата Ivan123 @
              SizeBufIn*4); ????


              Ты имеешь в виду SizeBufOut*4 из коды выше?
              По моей логике должно быть SizeBufOut*2, т.к. Vdata составляет 400 значений типа integer, которое 2 байтное. Попробуй использовать SizeOf(Vdata)
                Цитата ^D^ima @
                Попробуй использовать SizeOf(Vdata)

                Для того чтобы в третьем приложении мне получить 400 значений мне из второго приложения приходиться отправлять эти 400 значений как SizeBufIn*4, а в тетьем получать как SizeBufOut*4

                Добавлено
                Цитата Ivan123 @
                эти 400 значений как SizeBufIn*4

                отправить и прочитать 400 или 1600 значений разница большая когда передача и приём on-line
                Сообщение отредактировано: Ivan123 -
                  каждый тип данных имеет свой размер, вы записываете в массив Vdata 400 типов данных integer, поэтому, если один integer имеет размкр 4 байта, то 400*4=1600 байт.

                  процедура CopyMemory требует третьим аргументом указывать длину в байтах, потому, что она не знает какой тип данных она будет копировать в буфер указанный вторым аргументом, поэтому она копирует SizeBufOut*4, что равно 1600 байт.

                  как написали выше запись SizeBufOut*4 эквивалентна SizeOf(Vdata) при статическом массиве, при динамическом массиве SizeOf будет равен 4 байта.
                    Цитата vasya2019 @
                    если один integer имеет размкр 4 байта

                    с чего вдруг интегер весит 4 байта?
                      а сколько?
                        Это я с Word спутал, действительно 4 байта получается. Тогда все сходится 400*4 получается
                          Цитата vasya2019 @
                          один integer имеет размкр 4 байта, то 400*4=1600 байт

                          Спасибо всем за быстрое реагирование, запутался в размерности данных, теперь всё встало на свои места)
                          Сообщение отредактировано: Ivan123 -
                          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                          0 пользователей:


                          Рейтинг@Mail.ru
                          [ Script execution time: 0,0423 ]   [ 17 queries used ]   [ Generated: 19.04.24, 22:47 GMT ]