Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
prog:lazarus:cas:processus:shared_memory [13/01/2019 18:28] thierry ↷ Page déplacée de shared_memory à tehcnos:lazarus:shared_memory |
prog:lazarus:cas:processus:shared_memory [12/03/2023 17:21] (Version actuelle) thierry [Mémoire partagée] |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
====== Mémoire partagée ====== | ====== Mémoire partagée ====== | ||
+ | Ma problématique est de faire communiquer deux applications différentes (sur le même PC) entre elles... | ||
+ | |||
+ | Voici quelques pistes : | ||
+ | ===== Utilisation d'une classe TTICSharedMemory ===== | ||
+ | Ci dessous un exemple de données partagées entre deux applications Windows.\\ | ||
+ | Un serveur avec un ''TEdit'', qui modifie la mémoire partagé dés qu'on modifie la valeur du ''TEdit''.\\ | ||
+ | Un Client, qui affiche toutes les secondes la valeur de la donnée partagée. | ||
+ | ==== uTICSharedMemory ==== | ||
+ | Cette unité contient le code de l'object TTICSharedMemory | ||
+ | |||
+ | |||
+ | <code delphi uTICSharedMemory> | ||
+ | unit uTICSharedMemory; | ||
+ | |||
+ | {$mode ObjFPC}{$H+} | ||
+ | |||
+ | interface | ||
+ | |||
+ | uses | ||
+ | Windows; | ||
+ | |||
+ | type | ||
+ | |||
+ | { TTICSharedMemory } | ||
+ | |||
+ | TTICSharedMemory = class | ||
+ | private | ||
+ | FPointer: Pointer; | ||
+ | FLastError: DWord; | ||
+ | FHandle: THandle; | ||
+ | procedure FreeHandle; | ||
+ | public | ||
+ | // AName = l'identifiant du fichier partagé en mémoire | ||
+ | // ASize = la taille totale des données partagées | ||
+ | constructor Create(AName: PChar; ASize: integer); | ||
+ | | ||
+ | destructor Destroy; override; | ||
+ | property LastError: DWord read FLastError; | ||
+ | |||
+ | // Pointer = l'adresse de la donnée partagée | ||
+ | property Pointer: pointer read FPointer; | ||
+ | end; | ||
+ | |||
+ | implementation | ||
+ | |||
+ | { TTICSharedMemory } | ||
+ | |||
+ | procedure TTICSharedMemory.FreeHandle; | ||
+ | begin | ||
+ | if FHandle <> 0 then | ||
+ | begin | ||
+ | CloseHandle(FHandle); | ||
+ | FHandle := 0; | ||
+ | end; | ||
+ | end; | ||
+ | |||
+ | constructor TTICSharedMemory.Create(AName: PChar; ASize: integer); | ||
+ | begin | ||
+ | FHandle := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, | ||
+ | 0, ASize, AName); | ||
+ | FLastError := GetLastError; | ||
+ | |||
+ | if FHandle > 0 then | ||
+ | begin | ||
+ | FPointer := MapViewOfFile(FHandle, FILE_MAP_WRITE, 0, 0, 0); | ||
+ | if not assigned(FPointer) then FreeHandle; | ||
+ | end; | ||
+ | end; | ||
+ | |||
+ | destructor TTICSharedMemory.Destroy; | ||
+ | begin | ||
+ | if assigned(FPointer) then | ||
+ | begin | ||
+ | UnmapViewOfFile(FPointer); | ||
+ | FPointer := nil; | ||
+ | end; | ||
+ | FreeHandle; | ||
+ | inherited; | ||
+ | end; | ||
+ | |||
+ | end. | ||
+ | </code> | ||
+ | ==== Le Client ==== | ||
+ | Cette unité contient le code du client.\\ | ||
+ | C'est un ''TForm'' avec un ''TMemo'' et un ''TTimer''.\\ | ||
+ | Toutes les secondes il accéde a la mémoire partagé et affiche son contenu dans le ''TMemo'' | ||
+ | |||
+ | <code delphi uFormClient.pas> | ||
+ | unit uFormClient; | ||
+ | |||
+ | {$mode objfpc}{$H+} | ||
+ | |||
+ | interface | ||
+ | |||
+ | uses | ||
+ | SysUtils, | ||
+ | Forms, | ||
+ | Controls, | ||
+ | Graphics, | ||
+ | Dialogs, | ||
+ | StdCtrls, | ||
+ | ExtCtrls, | ||
+ | uTICSharedMemory; | ||
+ | |||
+ | type | ||
+ | |||
+ | // La structure qui sera échangée entre les deux applications | ||
+ | TDatas = packed record | ||
+ | Text: shortstring; | ||
+ | Size: integer; | ||
+ | Date: TDateTime; | ||
+ | end; | ||
+ | |||
+ | PDatas = ^TDatas; | ||
+ | |||
+ | { TFormClient } | ||
+ | |||
+ | TFormClient = class(TForm) | ||
+ | Memo: TMemo; | ||
+ | Timer1: TTimer; | ||
+ | procedure FormCreate(Sender: TObject); | ||
+ | procedure Timer1Timer(Sender: TObject); | ||
+ | private | ||
+ | FSMem: TTICSharedMemory; | ||
+ | FPDatas: PDatas; | ||
+ | public | ||
+ | |||
+ | end; | ||
+ | |||
+ | var | ||
+ | FormClient: TFormClient; | ||
+ | |||
+ | implementation | ||
+ | |||
+ | {$R *.lfm} | ||
+ | |||
+ | { TFormClient } | ||
+ | |||
+ | procedure TFormClient.FormCreate(Sender: TObject); | ||
+ | begin | ||
+ | FSMem := TTICSharedMemory.Create('shmemtest', sizeof(TDatas)); | ||
+ | FPDatas := FSMem.Pointer; | ||
+ | end; | ||
+ | |||
+ | procedure TFormClient.Timer1Timer(Sender: TObject); | ||
+ | begin | ||
+ | Memo.Lines.Add(DateTimeToStr(FPDatas^.Date)); | ||
+ | Memo.Lines.Add(FPDatas^.Text); | ||
+ | Memo.Lines.Add('Longueur:%d', [FPDatas^.Size]); | ||
+ | end; | ||
+ | |||
+ | end. | ||
+ | </code> | ||
+ | ==== Le Serveur ==== | ||
+ | Un ''TForm'' contenant un ''TEdit''.\\ | ||
+ | Dés que l'on modifie le ''TEdit'' il met a jour la mémoire partagée. | ||
+ | |||
+ | <code delphi uFormServer.pas> | ||
+ | unit uFormServer; | ||
+ | |||
+ | {$mode objfpc}{$H+} | ||
+ | |||
+ | interface | ||
+ | |||
+ | uses | ||
+ | Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls, | ||
+ | uTICSharedMemory; | ||
+ | |||
+ | type | ||
+ | |||
+ | // Structure de données partagée | ||
+ | TDatas = packed record | ||
+ | Text: shortstring; | ||
+ | Size: integer; | ||
+ | Date: TDateTime; | ||
+ | end; | ||
+ | |||
+ | PDatas = ^TDatas; | ||
+ | |||
+ | { TFormServer } | ||
+ | |||
+ | TFormServer = class(TForm) | ||
+ | Edit1: TEdit; | ||
+ | procedure Edit1Change(Sender: TObject); | ||
+ | procedure FormCreate(Sender: TObject); | ||
+ | procedure FormDestroy(Sender: TObject); | ||
+ | private | ||
+ | FPDatas: PDatas; | ||
+ | FSMem : TTICSharedMemory; | ||
+ | public | ||
+ | |||
+ | end; | ||
+ | |||
+ | var | ||
+ | FormServer: TFormServer; | ||
+ | |||
+ | implementation | ||
+ | |||
+ | {$R *.lfm} | ||
+ | |||
+ | { TFormServer } | ||
+ | |||
+ | procedure TFormServer.FormCreate(Sender: TObject); | ||
+ | begin | ||
+ | FSMem:=TTICSharedMemory.Create('shmemtest',sizeof(TDatas)); | ||
+ | FPDatas:=FSMem.Pointer; | ||
+ | end; | ||
+ | |||
+ | procedure TFormServer.FormDestroy(Sender: TObject); | ||
+ | begin | ||
+ | FSMem.Free; | ||
+ | end; | ||
+ | |||
+ | procedure TFormServer.Edit1Change(Sender: TObject); | ||
+ | begin | ||
+ | // Modification de la mémoire partagée | ||
+ | FPDatas^.Text:=Edit1.Text+#0; | ||
+ | FPDatas^.Size:=length(Edit1.Text); | ||
+ | FPDatas^.Date:=now; | ||
+ | end; | ||
+ | |||
+ | |||
+ | end. | ||
+ | </code> | ||
===== A voir ===== | ===== A voir ===== | ||
+ | <note important>Apparement ''shmat'' est propre a Linux/Unix</note> | ||
* [[https://www.developpez.net/forums/d1143012/c-cpp/c/memoire-commune-entre-processus-shmat/]] | * [[https://www.developpez.net/forums/d1143012/c-cpp/c/memoire-commune-entre-processus-shmat/]] | ||
* [[https://www.freepascal.org/docs-html/rtl/ipc/shmat.html]] | * [[https://www.freepascal.org/docs-html/rtl/ipc/shmat.html]] |