Здравствуйте!
Прошу помочь с примером кода, как реализовать в PB передачу строки, из одного экземпляра приложения во второй экземпляр этого же приложения, через файл в разделяемой памяти, или иным максимально быстрым и не ресурсозатратным способом.
PureBasic - форум |
Привет, Гость! Войдите или зарегистрируйтесь.
Вы здесь » PureBasic - форум » Вопросы по PureBasic » Передача строки между двумя экземплярами приложения, через память.
Здравствуйте!
Прошу помочь с примером кода, как реализовать в PB передачу строки, из одного экземпляра приложения во второй экземпляр этого же приложения, через файл в разделяемой памяти, или иным максимально быстрым и не ресурсозатратным способом.
Передатчик:
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
Большое спасибо!
Проверил. Принципиально работает.
НО! Но у меня существует принципиальное разногласие с предложенным Вами решением.
Ваше решение тянет за собой включение в мой проект библиотек Gadget и Window, что влечет увеличение исполняемого файла моей программы примерно на 40 килобайт. Для меня это много. И это в условиях когда "наш район еще не полностью рассчитался с государством по шерсти и мясу".
Видимо я зря не указал в первом посте, что у меня программа абсолютно безоконная. Таково одно из требований.
Мне бы, что то на чистом WINAPi.
В любом случае спасибо, буду держать Ваш вариант, как запасной.
Функциями библиотеки Network создаете клиент и сервер и производите обмен через 127.0.0.1
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)
Здравствуйте!
Прошу помочь с примером кода, как реализовать в PB передачу строки, из одного экземпляра приложения во второй экземпляр этого же приложения, через файл в разделяемой памяти, или иным максимально быстрым и не ресурсозатратным способом.
Мало исходных данных. Например о каких системах идёт речь? Или чем не устраивает pipe? https://www.purebasic.com/documentation … index.html
Спасибо большое за помощь. Ваши посты заставили меня рыть инет с удвоенной силой, дабы найти то, что меня устраивает, по простоте, эффективности, быстродействию и малому объему.
И, таки нашел готовое решение. Правда в собственных загашниках, в архиве скачанном незнамо где и незнамо когда. Три маленькие процедуры решают мою задачу:
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)
Вы здесь » PureBasic - форум » Вопросы по PureBasic » Передача строки между двумя экземплярами приложения, через память.