Strings not passing across shared memory?

Just starting out? Need help? Post your questions and find answers here.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Strings not passing across shared memory?

Post by Mistrel »

Why is it that I can't pass a string across shared memory?

Application 1:

Code: Select all

Structure struct
	b.l
	s.s
	l.l
EndStructure

*hfm=CreateFileMapping_($FFFFFFFF,0,#PAGE_READWRITE,0,SizeOf(struct),"map")
*ptr.struct=MapViewOfFile_(*hfm,#FILE_MAP_WRITE,0,0,0)

*ptr\b=2
*ptr\s="string"
*ptr\l=700

Debug *ptr\b
Debug *ptr\s
Debug *ptr\l

OpenWindow(0,0,0,320,240,"Window 1")
Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow
Application 2:

Code: Select all

Structure struct
	b.l
	s.s
	l.l
EndStructure

*hfm=CreateFileMapping_($FFFFFFFF,0,#PAGE_READWRITE,0,SizeOf(struct),"map")
*ptr.struct=MapViewOfFile_(*hfm,#FILE_MAP_WRITE,0,0,0)

Debug *ptr\b
Debug *ptr\s
Debug *ptr\l

OpenWindow(0,0,0,320,240,"Window 2")
Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

I'm not sure exactly what your trying to accomplish here, ie what the main point is, the string passing or the file mapping, so sorry if I'm off base. If the string passing is the objective, this may be your ticket:

http://www.purebasic.fr/english/viewtopic.php?t=29781
BERESHEIT
User avatar
Rings
Moderator
Moderator
Posts: 1435
Joined: Sat Apr 26, 2003 1:11 am

Post by Rings »

its only a pointer (a long) for the string in the struct.

Code: Select all

Debug SizeOf(struct)
so use some copymemory or
readprocessmemory functions...
SPAMINATOR NR.1
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Your code essentially looks okay, it is as rings says, you're only passing the pointer to the string and not the string itself. The receiving application will receive the pointer okay, but will not be able to access the string itself because the string resides within the virtual memory of the first application and is thus still inaccessible to the receiving app.

To pass a string this way you either have to write the string itself (use utf-8 format) to the shared memory or create a global atom and write the atom to the shared memory etc. In the following link I write an array of strings :

http://www.purebasic.fr/english/viewtop ... 64&start=0

Alternatively, use the method outlined by netmaestro above.
I may look like a mule, but I'm not a complete ass.
User avatar
helpy
Enthusiast
Enthusiast
Posts: 552
Joined: Sat Jun 28, 2003 12:01 am

Post by helpy »

Try it with fixed strings:

Code: Select all

Structure struct
   b.l
   s.s{16}
   l.l
EndStructure

*hfm=CreateFileMapping_($FFFFFFFF,0,#PAGE_READWRITE,0,SizeOf(struct),"map")
*ptr.struct=MapViewOfFile_(*hfm,#FILE_MAP_WRITE,0,0,0)

*ptr\b=2
*ptr\s="string"
*ptr\l=700

Debug *ptr\b
Debug *ptr\s
Debug *ptr\l

OpenWindow(0,0,0,320,240,"Window 1")
Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow
and this:

Code: Select all

Structure struct
   b.l
   s.s{16}
   l.l
EndStructure

*hfm=CreateFileMapping_($FFFFFFFF,0,#PAGE_READWRITE,0,SizeOf(struct),"map")
*ptr.struct=MapViewOfFile_(*hfm,#FILE_MAP_WRITE,0,0,0)

Debug *ptr\b
Debug *ptr\s
Debug *ptr\l

OpenWindow(0,0,0,320,240,"Window 2")
Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow
cu, guido
Windows 10 / Windows 7
PB Last Final / Last Beta Testing
schic
User
User
Posts: 34
Joined: Fri Sep 12, 2003 10:17 am

Post by schic »

here´s some code, quickly picked together from my project.
Maybe it helps you to use FileMapping.
Start the program 2 times, select a tree node and copy
and paste as you like.

Code: Select all


Global FilMapName.s = "MyUnique_MemName"
Global message_copy_id.l
Global MyClipboardMem.l, HandleMap.l, try2close.l

Structure MyStruct
  b.l
  s.s
  Level.l
EndStructure

Global NewList CopyList.MyStruct()
Global NewList ThisList.MyStruct()

Procedure.l AllocateMemoryGlobal(name.s, Size.l); allocate shared memory (name has to be unique)
  
  closeres = CloseHandle_(HandleMap)
  
  ;HandleMap = CreateFileMapping_(#INVALID_HANDLE_VALUE, 0, #PAGE_READWRITE, 0, Size, @name);#INVALID_HANDLE_VALUE ;$FFFFFFFF
  HandleMap = CreateFileMapping_($FFFFFFFF, 0, 402653188, 0, Size, @name)
  LastError = GetLastError_()
  If LastError = #ERROR_ALREADY_EXISTS ; =183
    i = 0
    While closeres = 1
      try2close = #True
      PostMessage_(#HWND_BROADCAST, message_copy_id, 0, i)
      i + 1
      Delay(10)
      closeres = CloseHandle_(HandleMap);: HandleMap = 0
    Wend
    HandleMap = CreateFileMapping_($FFFFFFFF, 0, 402653188, 0, Size, @name)
    LastError = GetLastError_()
  EndIf
  
  If HandleMap
    ; If LastError = #ERROR_ALREADY_EXISTS ; =183
    ; Debug "#ERROR_ALREADY_EXISTS !!!!!!!!!!!!"
    ; EndIf
    ProcedureReturn MapViewOfFile_(HandleMap, 983071, 0, 0 ,0);#FILE_MAP_WRITE ;983071
  Else
    ProcedureReturn 0
  EndIf
  
EndProcedure


Procedure.l Txt2Mem(lpMem, txt$)
  Protected tmpLen.l
  tmpLen = Len(txt$)
  CopyMemory(@tmpLen, lpMem, 4): lpMem + 4
  If tmpLen
    CopyMemory(@txt$, lpMem, tmpLen)
  EndIf
  lpMem + tmpLen
  ProcedureReturn lpMem
EndProcedure

Procedure CopyListNode(Index.l)
  If Not Index = -1
    If CountList(ThisList())
      SelectElement(ThisList(), Index)
      *oldElement = @ThisList()
      ;ClearList(CopyList()) 
      memLenNode = 0
      aktEbene = ThisList()\Level
      i=Index:nodes=0
      memLenNode + 8 ;first variable will be length of whole memory and second will be number of nodes
      Repeat
        With ThisList()
          memLenNode + 5 ; length in bytes of all longs and doubels etc. (not strings)
          memLenNode + Len(\s)        ;string nr 1
          memLenNode + 1*4 ; for writing the length of the string (one long for each)
        EndWith
        nodes+1
        i+1 
      Until NextElement(ThisList())=0 Or ThisList()\Level <= aktEbene
      
      ChangeCurrentElement(ThisList(), *oldElement)
      ; SysInfo.SYSTEM_INFO
      ; GetSystemInfo_(@SysInfo)
      ; memLenNode = Round(memLenNode/SysInfo\dwPageSize, 1)*SysInfo\dwPageSize*
      MyClipboardMem = AllocateMemoryGlobal(FilMapName, memLenNode*2)
      CopyMemory(@memLenNode, MyClipboardMem, 4)  ; write first length of memory
      *ClipBoardPointer = MyClipboardMem + 4
      CopyMemory(@nodes, *ClipBoardPointer, 4)       ; then number of nodes
      *ClipBoardPointer + 4
      Repeat
        With ThisList()
          CopyMemory(@\b, *ClipBoardPointer, 4): *ClipBoardPointer + 1
          *ClipBoardPointer = Txt2Mem(*ClipBoardPointer, \s)
          CopyMemory(@\Level, *ClipBoardPointer, 8): *ClipBoardPointer + 4
        EndWith
      Until NextElement(ThisList())=0 Or ThisList()\Level <= aktEbene
      unmapres = UnmapViewOfFile_(MyClipboardMem): MyClipboardMem = 0
      
      ChangeCurrentElement(ThisList(), *oldElement)
      Debug "nodes: " + Str(nodes)
      PostMessage_(#HWND_BROADCAST, message_copy_id, memLenNode, nodes)
      
    EndIf
  EndIf
EndProcedure

Procedure.s GetTxtFromMem(lpSrcMem, *TxtLen)
  Protected retTxt$
  tmpTxtLen = PeekL(lpSrcMem)
  MemOffset = tmpTxtLen+4
  CopyMemory(@MemOffset, *TxtLen, 4)
  If tmpTxtLen = 0
    retTxt$ = ""
  Else
    retTxt$ = PeekS(lpSrcMem+4, tmpTxtLen)
  EndIf
  ProcedureReturn retTxt$
EndProcedure

Procedure CopyMem2CopyList(Mem, MemLen, nodes)
  
  *ClipBoardPointer = Mem+8
  tmpLen.l=0
  i=0
  ClearList(CopyList())
  For i = 1 To nodes
    ;Repeat
    ;While *ClipBoardPointer < EndMem
    AddElement(CopyList())
    With CopyList()
      \b = PeekB(*ClipBoardPointer):*ClipBoardPointer+1
      \s = GetTxtFromMem(*ClipBoardPointer, @tmpLen):*ClipBoardPointer+tmpLen
      \Level = PeekL(*ClipBoardPointer):*ClipBoardPointer+4
    EndWith
    ;Wend
    ;Until *ClipBoardPointer >= EndMem
  Next
  
EndProcedure

Procedure Proc_Copy(wParam, lParam)
  ;#####################################################################################################
  ;# with OpenFileMapping we can not recognize if the mapped file is from this instance or another one #
  ;#####################################################################################################
  ; ThisHandleMap = OpenFileMapping_(#FILE_MAP_ALL_ACCESS, #False, FilMapName)
  ; If HandleMap
  ; MyClipboardMem = MapViewOfFile_(ThisHandleMap, #FILE_MAP_READ, 0, 0, *sender\wParam)
  ; CopyMem2CopyList(MyClipboardMem, *sender\wParam, *sender\lParam)
  ; unmapres = UnmapViewOfFile_(MyClipboardMem)
  ; closeres = CloseHandle_(HandleMap)
  ; closeres = CloseHandle_(ThisHandleMap)
  ; EndIf
  
  If wParam = 0 And lParam = 0 And try2close = #False
    ;Debug "am here at Proc_Copy to close mapped file handle"
    ; if try2close = #true -> trying to close from this instance 
    ; after MyClipboardMem is filled, but not read
    ; cause the posted message (message_copy_id) from this instance is 
    ; receieved not before MyClipboardMem is filled, 
    ; but before MyClipboardMem is read
    ; -> we don´t close the Mapped-File-Handle before try2close = #False
    
    ; we are here at Proc_Copy to close mapped file handle 
    ; cause another instance has asked for starting to copy
    ; and does need free filemapping
    unmapres = UnmapViewOfFile_(MyClipboardMem): MyClipboardMem = 0
    closeres = CloseHandle_(HandleMap)
    HandleMap = 0
    ClearList(CopyList())
    
    ProcedureReturn
  ElseIf wParam = 0 And lParam
    ;Debug "am here at Proc_Copy for Nothing"
    ; *sender\lParam > 0 -> message_copy_id already posted so don´t close any more
    ProcedureReturn
  EndIf
  
  ;Debug "am here at Proc_Copy to copy"
  ;now we copy MyClipboardMem to the CopyList if the mapped file ALREADY EXISTS
  If Not HandleMap
    HandleMap = CreateFileMapping_($FFFFFFFF, 0, 402653188, 0, wParam, @FilMapName)
    LastError = GetLastError_()
    If HandleMap
      If LastError = #ERROR_ALREADY_EXISTS ; =183
        ;Debug "created MyClipboardMem from other proc"
        ; -> we have MyClipboardMem from other proc cause LastError = #ERROR_ALREADY_EXISTS and HandleMap = 0
        MyClipboardMem = MapViewOfFile_(HandleMap, 983071, 0, 0 ,0);#FILE_MAP_WRITE ;983071
        ;otherProc.b = #True
      EndIf
    Else
      ;Debug "no HandleMap from CreateFileMapping"
      closeres = CloseHandle_(HandleMap)
      HandleMap = 0
    EndIf
  Else
    ;Debug "created MyClipboardMem from THIS proc"
    ; we have MyClipboardMem from This proc cause HandleMap already exists
    MyClipboardMem = MapViewOfFile_(HandleMap, 983071, 0, 0 ,0);#FILE_MAP_WRITE ;983071
    ;otherProc.b = #False
  EndIf
  
  ;Debug "MyClipboardMem in Proc_Copy: " + Str(MyClipboardMem)
  If MyClipboardMem
    CopyMem2CopyList(MyClipboardMem, wParam, lParam)
    unmapres = UnmapViewOfFile_(MyClipboardMem)
    ;Debug "unmapres: " + Str(unmapres) + " ###############" 
    MyClipboardMem = 0
    try2close = #False ; MyClipboardMem is read so we can try to close mapped file next time we are asked to
  EndIf
  
EndProcedure

Procedure InsertListNode(Index.l)
  Protected tmpText$
  
  If CountList(ThisList())
    SelectElement(ThisList(), Index)
    
    i=Index
    ForEach CopyList()
      AddElement(ThisList())
      
      With ThisList()
        \b      = CopyList()\b
        \s      = CopyList()\s
        \Level  = CopyList()\Level
      EndWith
      
      i+1 
      AddGadgetItem(0, i, ThisList()\s, 0, ThisList()\Level)
    Next
  EndIf ;If CountList(ThisList())
  
EndProcedure
  

Procedure MyWindowCallback(WindowID, message, wParam, lParam)
  result = #PB_ProcessPureBasicEvents
  Select message
    Case message_copy_id
      Proc_Copy(wParam, lParam)
  EndSelect
  
  ProcedureReturn result
EndProcedure

Procedure AddTreeData(any.b, txt$, SubLevel.l)
  AddGadgetItem (0, -1, txt$, 0, SubLevel)
  AddElement(ThisList()): ThisList()\b=any: ThisList()\s=txt$: ThisList()\Level=SubLevel
EndProcedure


If OpenWindow(0, 0, 0, 355, 180, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
  
  ; lets look if there is any copy-data from an earlier running instance 
  ; mapped in memory and if, take it and free (unmap) the mapped memory
  HandleMap = CreateFileMapping_($FFFFFFFF, 0, 402653188, 0, 16, @FilMapName)
  If HandleMap
    LastError = GetLastError_()
    If LastError = #ERROR_ALREADY_EXISTS
      MyClipboardMem = MapViewOfFile_(HandleMap, #FILE_MAP_ALL_ACCESS, 0, 0, 0)
      MemLen = PeekL(MyClipboardMem)
      nodes = PeekL(MyClipboardMem+4)
      CopyMem2CopyList(MyClipboardMem, MemLen, nodes)
      UnmapViewOfFile_(MyClipboardMem): MyClipboardMem = 0
    EndIf
  EndIf
  
  SetWindowCallback(@MyWindowCallback(), 0)
  TreeGadget(0, 10, 10, 160, 160)
  For a = 0 To 10
    AddTreeData(a, "Normal Item "+Str(a), 0)
    AddTreeData(a, "Node "+Str(a), 0)
    AddTreeData(a, "Sub-Item 1", 1)
    AddTreeData(a, "Sub-Item 2", 1)
    AddTreeData(a, "Sub-Item 3", 1)
    AddTreeData(a, "Sub-Item 4", 1)
    AddTreeData(a, "File "+Str(a), 0)
  Next
  ButtonGadget(1, 180, 10, 160, 20, "Copy")
  ButtonGadget(2, 180, 40, 160, 20, "Paste")
  
  message_copy_id = RegisterWindowMessage_("MyCopyMessage")
  
  Repeat
    Event       = WaitWindowEvent()
    WindowID    = EventWindow()
    GadgetID    = EventGadget()
    GadgetEvent = EventType()
    
    
    Select Event
      Case #PB_Event_Gadget
        Select GadgetID
          Case 1
            CopyListNode(GetGadgetState(0))
          Case 2
            InsertListNode(GetGadgetState(0))
        EndSelect
    EndSelect
    
    
  Until Event = #PB_Event_CloseWindow
EndIf
Post Reply