PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Передача строки между двумя экземплярами приложения, через память.


Передача строки между двумя экземплярами приложения, через память.

Сообщений 1 страница 7 из 7

1

Здравствуйте!

Прошу помочь с примером кода, как реализовать в PB передачу строки, из одного экземпляра приложения во второй экземпляр этого же приложения, через файл в разделяемой памяти, или иным максимально быстрым и не ресурсозатратным способом.

0

2

Передатчик:

Код:
Enumeration 
  #Window_0 
EndEnumeration 
Enumeration 
  #Button_0 
  #String_1 
EndEnumeration 
Procedure OpenWindow_Window_0() 
  If OpenWindow(#Window_0, 438, 414, 412, 118, "Window_0", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_TitleBar) 
    CreateGadgetList(WindowID(#Window_0))
    ButtonGadget(#Button_0, 240, 75, 150, 20, "Send") 
    StringGadget(#String_1, 10, 25, 385, 20, "") 
  EndIf 
EndProcedure 
OpenWindow_Window_0() 
cds.COPYDATASTRUCT 
Repeat 
  Event = WaitWindowEvent() 
  Select Event 
    Case #PB_Event_Gadget 
      EventGadget = EventGadget() 
      EventType = EventType() 
      If EventGadget = #Button_0 
        buffer.s = GetGadgetText(#String_1) 
        If buffer  
          cds\cbData = Len(buffer) + 1 
          cds\lpData = @buffer 
          hWnd = FindWindow_(#Null, "Receiver") 
          If hWnd 
            SendMessage_(hWnd, #WM_COPYDATA, 0, @cds) 
          EndIf 
        EndIf  
      ElseIf EventGadget = #String_1 
      EndIf 
    Case #PB_Event_CloseWindow 
      EventWindow = EventWindow() 
      If EventWindow = #Window_0 
        CloseWindow(#Window_0) 
        Break 
      EndIf 
  EndSelect 
ForEver

Приемник:

Код:
Enumeration 
  #Receiver 
EndEnumeration 
Enumeration 
  #Text_0 
EndEnumeration 
Procedure OpenWindow_Receiver() 
  If OpenWindow(#Receiver, 443, 401, 400, 126, "Receiver", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_TitleBar) 
     CreateGadgetList(WindowID(#Receiver))
    TextGadget(#Text_0, 5, 35, 380, 25, "") 
  EndIf 
EndProcedure 

Procedure Callback(WindowID, Message, wParam, lParam) 
  Select Message 
     Case #WM_COPYDATA 
       *adr.COPYDATASTRUCT = lParam 
       If *adr 
         string$ + PeekS(*adr\lpData, *adr\cbData) 
         SetGadgetText(#Text_0, string$) 
       EndIf  
  EndSelect      
  ProcedureReturn #PB_ProcessPureBasicEvents      
EndProcedure  

OpenWindow_Receiver() 
SetWindowCallback(@Callback()) 
Repeat 
  Event = WaitWindowEvent() 
  Select Event 
    Case #PB_Event_Gadget 
      EventGadget = EventGadget() 
      EventType = EventType() 
      If EventGadget = #Text_0 
      EndIf 
    Case #PB_Event_CloseWindow 
      EventWindow = EventWindow() 
      If EventWindow = #Receiver 
        CloseWindow(#Receiver) 
        Break 
      EndIf 
  EndSelect 
ForEver

0

3

КЭС написал(а):

Большое спасибо!
Проверил. Принципиально работает.
НО! Но у меня существует принципиальное разногласие с предложенным Вами решением.
Ваше решение тянет за собой включение в мой проект библиотек Gadget и Window, что влечет увеличение исполняемого файла моей программы примерно на 40 килобайт. Для меня это много. И это в условиях когда "наш район еще не полностью рассчитался с государством по шерсти и мясу":dontknow:
Видимо я зря не указал в первом посте, что у меня программа абсолютно безоконная. Таково одно из требований.
Мне бы, что то на чистом WINAPi.
В любом случае спасибо, буду держать Ваш вариант, как запасной.

0

4

Функциями библиотеки Network создаете клиент и сервер и производите обмен через 127.0.0.1

0

5

SharedMem_module.pbi:

Код:
; Спиздишен и модифиед коде фром хере https://www.purebasic.fr/english/viewtopic.php?f=12&t=43875 
; by LinXP
; описание https://www.frolov-lib.ru/books/bsp/v27/ch2_1.htm
DeclareModule SharedMemory
  #ModuleName$ = "SharedMemory"
  #VersionName$ = "1.0.0"
  
  Declare CreateMap(MapName.s, Size.q, Inherit=#False)
  Declare.s GetMapString(MapName.s)
  Declare SetMapString(MapName.s, Value.s)
  Declare CloseMap(hMap)
  Declare GetMapPtr(MapName.s)
  Declare CloseMapPtr(*MapPtr) 
  Declare SetMapStructure(MapName.s, *Value)
EndDeclareModule
Module SharedMemory
  
  Procedure CreateMap(MapName.s, Size.q, Inherit=#False)
    Protected hFileMap
    Protected *MapView
    Protected Security.SECURITY_ATTRIBUTES
    
    Security\nLength=SizeOf(SECURITY_ATTRIBUTES)
    Security\bInheritHandle=Inherit
    hFileMap=CreateFileMapping_(-1,@Security,#PAGE_READWRITE, PeekL(@Size.q+SizeOf(Long)),PeekL(@Size.q),@MapName.s)
    
    If Not hFileMap
      ProcedureReturn #False
    EndIf
    
    ProcedureReturn hFileMap
  EndProcedure
  
  Procedure.s GetMapString(MapName.s)
    Protected hFileMap
    Protected *MapView
    Protected Value.s
    
    hFileMap=OpenFileMapping_(#FILE_MAP_ALL_ACCESS,0,@MapName.s)
    
    If Not hFileMap
      ProcedureReturn ""
    EndIf
    
    *MapView=MapViewOfFile_(hFileMap,#FILE_MAP_WRITE,0,0,0)
    
    If Not *MapView
      CloseHandle_(hFileMap)
      ProcedureReturn ""
    EndIf
    
    ;/ Read the map value to the file
    Value.s=PeekS(*MapView)
    
    ;/ Unmap the mapped view of the file from memory
    UnmapViewOfFile_(*MapView)
    
    CloseHandle_(hFileMap)
    
    ProcedureReturn Value.s
  EndProcedure
  
  Procedure SetMapString(MapName.s, Value.s)
    Protected hFileMap
    Protected *MapView
    
    hFileMap=OpenFileMapping_(#FILE_MAP_ALL_ACCESS,0,@MapName.s)
    
    If Not hFileMap
      ProcedureReturn #False
    EndIf
    
    *MapView=MapViewOfFile_(hFileMap,#FILE_MAP_WRITE,0,0,0)
    
    If Not *MapView
      CloseHandle_(hFileMap)
      ProcedureReturn #False
    EndIf
    
    ;/ Write the map value to the file
    PokeS(*MapView,Value.s)
    
    ;/ Unmap the mapped view of the file from memory
    UnmapViewOfFile_(*MapView)
    
    CloseHandle_(hFileMap)
    
    ProcedureReturn #True
  EndProcedure
  
  Procedure GetMapPtr(MapName.s)
    Protected hFileMap
    Protected *MapView
    
    hFileMap=OpenFileMapping_(#FILE_MAP_ALL_ACCESS,0,@MapName.s)
    
    If Not hFileMap
      ProcedureReturn #False
    EndIf
    
    *MapView=MapViewOfFile_(hFileMap,#FILE_MAP_WRITE,0,0,0)
    
    If Not *MapView
      CloseHandle_(hFileMap)
      ProcedureReturn #False
    EndIf
    
    CloseHandle_(hFileMap)
    
    ProcedureReturn *MapView
  EndProcedure
  
  Procedure CloseMapPtr(*MapPtr)
    ;/ Unmap the mapped view of the file from memory
    If Not UnmapViewOfFile_(*MapPtr)
      ProcedureReturn #False
    EndIf
    
    ProcedureReturn #True
  EndProcedure
  
  Procedure CloseMap(hMap)
    If Not CloseHandle_(hMap)
      ProcedureReturn #True
    EndIf
    
    ProcedureReturn #False
  EndProcedure
  
  Procedure SetMapStructure(MapName.s, Value)
    Protected hFileMap
    Protected *MapView
    
    hFileMap=OpenFileMapping_(#FILE_MAP_ALL_ACCESS,0,@MapName.s)
    
    If Not hFileMap
      ProcedureReturn #False
    EndIf
    
    *Value=MapViewOfFile_(hFileMap,#FILE_MAP_WRITE,0,0,0)
    
    If Not *MapView
      CloseHandle_(hFileMap)
      ProcedureReturn #False
    EndIf
    
    ;/ Write the map value to the file
    ; PokeS(*MapView,Value.s)
    ; *MapView = *Value
    ;/ Unmap the mapped view of the file from memory
    UnmapViewOfFile_(*Value)
    
    CloseHandle_(hFileMap)
    
    ProcedureReturn #True
  EndProcedure
  
EndModule

; =================example=================
CompilerIf #PB_Compiler_IsMainFile
  
  
  MapName.s="TestMap222"
  
  hMap = SharedMemory::CreateMap(MapName.s,256)
  
  SharedMemory::SetMapString(MapName.s,"1")
  
  ;/ Output 1
  Debug SharedMemory::GetMapString(MapName.s)
  
  SharedMemory::SetMapString(MapName.s,"2")
  
  ;/ Output 2
  Debug SharedMemory::GetMapString(MapName.s)
  
  *MapView = SharedMemory::GetMapPtr(MapName.s)
  Debug *MapView 
  ;/ Output 2
  Debug PeekS(*MapView)
  Debug PeekS(*MapView)
  
  SharedMemory::CloseMapPtr(*MapView)
  
  SharedMemory::CloseMap(hMap)
  
  ;/ Output a blank string (the map is closed)
  Debug SharedMemory::GetMapString(MapName.s)
  
  
  MapNameStruc.s = "StrucParam"
  Structure SUBSET
    SubValB.b
    SubValL.l
    SubValF.f
  EndStructure
  Structure SETTINGS
    Value1.l
    Value2.l
    Value3.l
    SubVal.SUBSET
  EndStructure
  
  params.SETTINGS
  
  hMap2 = SharedMemory::CreateMap(MapNameStruc.s, SizeOf(SETTINGS))
  params\Value1 = 12345678
  params\Value2 = 87654321
  params\Value3 = 11223344
  params\SubVal\SubValB = 45
  params\SubVal\SubValF = 232.344
  params\SubVal\SubValL = 238597
  Debug    @params
  Debug  SharedMemory::SetMapStructure(MapNameStruc.s, @params)
  
  my_params.SETTINGS
  
CompilerEndIf

SharedMem_example.pb (скомпилить и запустить несколько копий)

Код:
XIncludeFile "SharedMem_module.pbi"

Global MapName1.s="TestMap1"
Global MapName2.s="TestMap2"
hMap1 = SharedMemory::CreateMap(MapName1.s,256)
hMap2 = SharedMemory::CreateMap(MapName2.s,256)
If SharedMemory::GetMapString(MapName1.s) = "" : SharedMemory::SetMapString(MapName1.s,"value 1") : EndIf
If SharedMemory::GetMapString(MapName2.s) = "" : SharedMemory::SetMapString(MapName2.s,"value 2") : EndIf

Global Window_0
Global Text_1, String_1, Button_1, Text_2, String_2, Button_2
Window_0 = OpenWindow(#PB_Any, #PB_Ignore, #PB_Ignore, 480, 100, "Shared Mem Example", #PB_Window_SystemMenu)
Text_1 = TextGadget(#PB_Any, 20, 10, 180, 25, "Param1:")
String_1 = StringGadget(#PB_Any, 200, 10, 180, 25, "This value 1")
Button_1 = ButtonGadget(#PB_Any, 390, 10, 80, 25, "Set")
Text_2 = TextGadget(#PB_Any, 20, 50, 180, 25, "Param2:")
String_2 = StringGadget(#PB_Any, 200, 50, 180, 25, "This value 2")
Button_2 = ButtonGadget(#PB_Any, 390, 50, 80, 25, "Set")

Repeat
  Event = WaitWindowEvent(10)
  SetGadgetText(Text_1, SharedMemory::GetMapString(MapName1.s))
  SetGadgetText(Text_2, SharedMemory::GetMapString(MapName2.s))
  Select event
    Case #PB_Event_CloseWindow
      
    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case Button_1
          SharedMemory::SetMapString(MapName1.s, GetGadgetText(String_1))
        Case Button_2
          SharedMemory::SetMapString(MapName2.s, GetGadgetText(String_2))        
      EndSelect
  EndSelect
Until Event = #PB_Event_CloseWindow

SharedMemory::CloseMap(hMap1)
SharedMemory::CloseMap(hMap2)

Отредактировано Lin (17.01.2021 21:48:16)

0

6

kichrot написал(а):

Здравствуйте!

Прошу помочь с примером кода, как реализовать в PB передачу строки, из одного экземпляра приложения во второй экземпляр этого же приложения, через файл в разделяемой памяти, или иным максимально быстрым и не ресурсозатратным способом.

Мало исходных данных. Например о каких системах идёт речь? Или чем не устраивает pipe? https://www.purebasic.com/documentation … index.html

0

7

КЭС написал(а):
Пётр написал(а):
Lin написал(а):
useful написал(а):

Спасибо большое за помощь. Ваши посты заставили меня рыть инет с удвоенной силой,  дабы найти то, что меня устраивает, по простоте, эффективности, быстродействию и малому объему.
И, таки нашел готовое решение. Правда в собственных загашниках, в архиве скачанном незнамо где и незнамо когда. Три маленькие процедуры решают мою задачу:

SharedMemory - Сервер:

Код:
; Автор: ts-soft
;http://www.purebasic.fr/german/viewtopic.php?p=198712#p198712

EnableExplicit

Define HandleMap.l

;создает или открывает совместно используемую именованную память,
; если память уже была создана под именем, она открывается и размер игнорируется.
; это соответствует OpenSharedMemory
Procedure AllocateSharedMemory(Name.s, Size.l)
    Shared HandleMap
    HandleMap = CreateFileMapping_(#INVALID_HANDLE_VALUE, 0, #PAGE_READWRITE|#SEC_COMMIT|#SEC_NOCACHE, 0, Size, @Name)
    If HandleMap
        ProcedureReturn MapViewOfFile_(HandleMap, #FILE_MAP_ALL_ACCESS, 0, 0, 0)
    EndIf
EndProcedure

; открывает именованную память, которая уже была создана
Procedure OpenSharedMemory(Name.s)
    Shared HandleMap
    HandleMap = OpenFileMapping_(#FILE_MAP_ALL_ACCESS, 0, @Name)
    If HandleMap
        ProcedureReturn MapViewOfFile_(HandleMap, #FILE_MAP_ALL_ACCESS, 0, 0, 0)
    EndIf
EndProcedure

; освобождает память для текущего процесса.
; только когда последний процесс освободил память, она наконец освобождается!
Procedure FreeSharedMemory(MemoryAddress.l)
    Shared HandleMap
    UnmapViewOfFile_(MemoryAddress)
    CloseHandle_(HandleMap)
EndProcedure

;--------------------------------------------------

Structure myMem
    text.s{23}
    quit.l
EndStructure

; тест
Define *mem.myMem = AllocateSharedMemory("MyMemory", SizeOf(myMem))

If *mem
    *mem\text = "Почувствуй Pure... Силу"
    
    While *mem\quit = #False
        Delay(100)
    Wend
    FreeSharedMemory(*mem)
    MessageRequester("MyMemory", "Клиент установил выход")
EndIf

SharedMemory - Клиент:

Код:
; Автор: ts-soft
;http://www.purebasic.fr/german/viewtopic.php?p=198712#p198712

EnableExplicit

Define HandleMap.l

;создает или открывает совместно используемую именованную память,
; если память уже была создана под именем, она открывается и размер игнорируется.
; это соответствует OpenSharedMemory
Procedure AllocateSharedMemory(Name.s, Size.l)
    Shared HandleMap
    HandleMap = CreateFileMapping_(#INVALID_HANDLE_VALUE, 0, #PAGE_READWRITE|#SEC_COMMIT|#SEC_NOCACHE, 0, Size, @Name)
    If HandleMap
        ProcedureReturn MapViewOfFile_(HandleMap, #FILE_MAP_ALL_ACCESS, 0, 0, 0)
    EndIf
EndProcedure

; открывает именованную память, которая уже была создана
Procedure OpenSharedMemory(Name.s)
    Shared HandleMap
    HandleMap = OpenFileMapping_(#FILE_MAP_ALL_ACCESS, 0, @Name)
    If HandleMap
        ProcedureReturn MapViewOfFile_(HandleMap, #FILE_MAP_ALL_ACCESS, 0, 0, 0)
    EndIf
EndProcedure

; освобождает память для текущего процесса.
; только когда последний процесс освободил память, она наконец освобождается!
Procedure FreeSharedMemory(MemoryAddress.l)
    Shared HandleMap
    UnmapViewOfFile_(MemoryAddress)
    CloseHandle_(HandleMap)
EndProcedure

;--------------------------------------------------

Structure myMem
    text.s{23}
    quit.l
EndStructure

; тест
Define *mem.myMem = OpenSharedMemory("MyMemory")

If *mem
    MessageRequester("MyMemory", *mem\text)
    
    *mem\quit = #True
    MessageRequester("quit", Str(*mem\quit)) ; чтоб увидеть сообщение сервера
    FreeSharedMemory(*mem)
EndIf

Отредактировано kichrot (18.01.2021 18:21:07)

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Передача строки между двумя экземплярами приложения, через память.