Здравствуйте!
Прошу помочь с примером кода, как реализовать в 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 » Передача строки между двумя экземплярами приложения, через память.