ShareMemory的问题(50分)

L

llzx

Unregistered / Unconfirmed
GUEST, unregistred user!
用DLL定义一个全局句柄,实现Form间的动态数据传输<br>为此我编了几个Demo,但是不能实现该功能,且Form关闭时,内存不能正确释放<br>望各位大侠指教<br>1.DLL<br>library shareDll;<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,sharemem,<br>&nbsp; StdCtrls, ExtCtrls;<br>var<br>&nbsp; hMem: THandle;<br>&nbsp; num : integer;<br><br>function GetGlobalMem: THandle;<br>begin<br>&nbsp; &nbsp;Result := hMem;<br>end;<br><br>exports<br>GetGlobalMem Index 1 resident;<br><br>begin<br>&nbsp; &nbsp;hMem := GlobalAlloc(gmem_MOVEABLE and gmem_DDEShare,num);<br>&nbsp; &nbsp;if hMem = 0 then<br>&nbsp; &nbsp; &nbsp; MessageDlg('Could not allocate memory',mtWarning,[mbOK],0);<br>end.<br><br>2.Server端<br>implementation<br><br>function GetGlobalMem:THandle;far;external 'shareDll.dll';<br><br>{$R *.DFM}<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br>hMem: THandle;<br>pMem: PChar;<br>S : string;<br>begin<br>&nbsp; &nbsp;hMem := GetGlobalMem; &nbsp; &nbsp;<br>&nbsp; &nbsp;if hMem &lt;&gt; 0 then<br>&nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp;pMem := GlobalLock(hMem); &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp;if pMem &lt;&gt; nil then<br>&nbsp; &nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StrPCopy(pMem,Memo1.text); &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GlobalUnlock(hMem); &nbsp; &nbsp; &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp;end<br>&nbsp; &nbsp; &nbsp; &nbsp;else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MessageDlg('Couldnot Lock memory block',mtWarning,[mbOK],0);<br>&nbsp; &nbsp;end;<br>&nbsp; &nbsp;s:=strpas(pmem);<br>// &nbsp; showmessage(s);<br><br>end;<br><br>procedure TForm1.Button2Click(Sender: TObject);<br>begin<br>&nbsp; close;<br>end;<br><br>3.client端<br>implementation<br>function GetGlobalMem:THandle;far;external 'shareDll.dll';<br><br>{$R *.DFM}<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br>&nbsp; &nbsp;hMem: THandle;<br>&nbsp; &nbsp;pMem: PChar;<br>begin<br>&nbsp; &nbsp;hMem := GetGlobalMem; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp;if hMem &lt;&gt; 0 then<br>&nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp;pMem := GlobalLock(hMem);<br>&nbsp; &nbsp; &nbsp; &nbsp;if pMem &lt;&gt; nil then<br>&nbsp; &nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Memo1.text := StrPas(pMem); &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;GlobalUnlock(hMem); &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp;end<br>&nbsp; &nbsp; &nbsp; &nbsp;else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MessageDlg('Couldnot Lock memory block',mtWarning,[mbOK],0);<br>&nbsp; &nbsp;end;<br>end;<br><br>procedure TForm1.Button2Click(Sender: TObject);<br>var<br>&nbsp; &nbsp;hMem: THandle;<br>&nbsp; &nbsp;pMem: PChar;<br>begin<br>&nbsp; &nbsp;hMem := GetGlobalMem; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br>&nbsp; &nbsp;Freelibrary(hMem);<br>&nbsp; &nbsp;close;<br>end;<br><br>&nbsp;问题:1.程序运行无任何错误,且Server,client都可以得到全局Handle<br>但是Client的Memo 不能得到正确数值<br>2。当client Formclose 时,总有Error 产生,不知道是什么<br><br>因为分不够多了,请斑竹及大侠多多包涵
 
我看你这里用到了far,现在编DLL最好用stdcall
 
<br>你的Server和Client不是同一个进程,不能这样共享内存<br>这是Win32内存管理和win31 dll的不同,<br>即Server的hmem和client的hmem不是同一个值<br><br>共享数据要使用memory file mapping或者wm_copydata,<br>使用memory file的例子你可以mail问我要,<br>或者查书&lt;delphi 3开发使用手册&gt;p640<br><br>
 
你还是mail 个exmple 给我吧。。。<br>stliu@email.hq.cninfo.net
 
应该在dll里释放mem
 
I'm unlucky: after I inputting so much chars here,<br>IE suddenly lcear them all!!!<br>I have to reinput, :(~~~~~<br><br>Here is an example:<br><br>uses Windows;<br>const MEM_FILENAME='SAMPLE_MEM_FILE';<br><br>type<br>TShared=record<br>{Define The structure of your shared data here}<br>end;<br>PShared=^TShared;<br><br>var<br>MemFile: THandle;<br>Shared : PShared;<br><br>Begin<br>// 通过建立内存映象文件以共享内存<br>MemFile:=OpenFileMapping(FILE_MAP_WRITE,False,<br>MEM_FILENAME);<br>if MemFile=0 then<br>MemFile:=CreateFileMapping(INVALID_HANDLE_VALUE,nil,PAGE_READWRITE,0,<br>SizeOf(TShared) ,MEM_FILENAME);<br>Shared:=MapViewOfFile(MemFile,File_MAP_WRITE,0,0,0);<br><br>// Release shared mem mapping here:<br>if (Shared&lt;&gt;NiL) begin<br>UnmapViewOfFile(Shared);<br>Shared := NiL;<br>end<br><br>if (MemFile&lt;&gt;INVALID_HANDLE_VALUE) Begin<br>CloseHandle(MemFile);<br>MemFile := INVALID_HANDLE_VALUE;<br>End;<br><br>End;<br><br>
 
pegasus 的答案正确,<br>但是共享数据使用memory file mapping或者wm_copydata,<br>时,那种效率更好且更加稳定呢。。。<br>jiangtao 的example 希望尽快发到,我再研究研究<br>stliu@email.hq.cninfo.net<br>
 
这要看你的程序要求了,如果你要求客户端可以修改数据,只能用内存映射文件了,<br>wm_copydata有很多限制,详细可参见win32的help.
 
客户端当然要允许修改数据,其实我也是想将全局变量存在Dll中供调用,<br>
 
在win32中,你不可能将全局变量放到dll中让二个或二个以上的进程共享,<br>这是由于win32中dll没有自己的局部堆,当一个进程装入dll时,系统会自动将<br>dll的数据和代码映射到该进程的地址空间,dll中的任何函数的内存分配请求<br>都是在被调用进程的地址空间中分配的,其它的进程无权访问这块内存.如果不用<br>内存映射文件,你不防试试用socket来进行客户端和服务端的通信和数据处理.
 
本来不想贴代码(站点速度太慢,帖子太长 ...),<br>但看讨论地如此热烈...<br><br>Win32 DLL可以实现多进程共享全局变量,<br>关键是方法和 Win16不一样,<br>用 memory file mapping是比较好的方法,<br>&nbsp;<br><br>library hookdll;<br><br>uses<br>&nbsp; Windows,<br>&nbsp; SysUtils,<br>&nbsp; Messages;<br><br><br><br>const<br>&nbsp; &nbsp; &nbsp; &nbsp; Key:String ='_GMEM';<br><br>&nbsp; WM_MOUSEPOS &nbsp;= WM_USER+1000;<br><br>type<br>&nbsp; &nbsp; &nbsp; &nbsp; PShareData = ^TShareData;<br>&nbsp; TShareData = record<br>&nbsp; &nbsp; hHookWnd: HWND;<br>&nbsp; &nbsp; inputText:array[0..100] of Byte;<br>&nbsp; end;<br><br><br>var<br>&nbsp; hObjHandle:THandle;<br>&nbsp; pGMem:pointer;<br><br>&nbsp; hNextMouseProc,hNextKeyBoardProc: hHook;<br><br>procedure UnMapMemory;<br>begin<br>&nbsp; &nbsp; &nbsp; &nbsp; if Assigned(pGMem) then<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; UnMapViewOfFile(pGMem);<br>&nbsp; &nbsp; &nbsp; pGmem := nil;<br>&nbsp; &nbsp; end;<br><br>&nbsp; if hObjhandle &gt; 0 then<br>&nbsp; &nbsp; &nbsp; &nbsp; CloseHandle(hObjHandle);<br><br>&nbsp; hObjHandle:=0;<br>end;<br><br>procedure MapMemory(dwAllocSize:DWORD);<br>begin<br>&nbsp; &nbsp; &nbsp; &nbsp; hObjHandle := CreateFileMapping(MAXDWORD,nil,PAGE_READWRITE,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0,dwAllocSize,PChar(key));<br>&nbsp; &nbsp; &nbsp; &nbsp; if hObjHandle = 0 then<br>&nbsp; &nbsp; &nbsp; &nbsp; Raise Exception.Create('Could not create file-mapping object');<br><br>&nbsp; &nbsp; &nbsp; &nbsp; pGmem := MapViewOfFile(hObjHandle,FILE_MAP_WRITE,0,0,1);<br>&nbsp; if not Assigned(pGMem) then<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; UnMapMemory;<br>&nbsp; &nbsp; &nbsp; Raise Exception.Create('Could not map file');<br>&nbsp; &nbsp; end;<br><br>end;<br><br><br><br>function MouseHookProc (nCode: Integer; wParam, lParam: Longint): Longint; stdcall;<br>var<br>&nbsp; &nbsp; &nbsp; &nbsp; PTemp:pInteger;<br>&nbsp; mPoint:TPoint;<br>&nbsp; &nbsp; &nbsp; &nbsp; mHookRecPtr : PMouseHookStruct;<br>begin<br>&nbsp; if nCode &lt; 0 then<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Result := CallNextHookEx (hNextMouseProc, nCode, wParam, lParam);<br>&nbsp; &nbsp; &nbsp; exit;<br>&nbsp; &nbsp; end;<br><br>&nbsp; if nCode &gt;= 0 then<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; if (wParam = WM_MOUSEMOVE) or (wParam = WM_NCMOUSEMOVE) then<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pTemp:=@PShareData(pGMem).hHookWnd;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mHookRecPtr := PMouseHookStruct(lParam);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mPoint := mHookRecPtr.pt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PostMessage(pTemp^,WM_MOUSEPOS,0,MakeLParam(mPoint.x,mPoint.y));<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end;<br>&nbsp; Result := CallNextHookEx (hNextMouseProc, nCode, wParam, lParam);<br>end;<br><br><br>procedure SetHookWnd(aHwnd:HWND);<br>var<br>&nbsp; &nbsp; &nbsp; &nbsp; pTemp: PInteger;<br>begin<br>&nbsp; &nbsp; &nbsp; &nbsp; pTemp:=@PShareData(pGMem).hHookWnd;;<br>&nbsp; PTemp^:=aHwnd;<br>end;<br><br><br>function InstallMouseHook(hw:HWND): BOOL;stdcall;<br>begin<br>&nbsp; Result := False;<br>&nbsp; if hNextMouseProc &lt;&gt; 0 then<br>&nbsp; &nbsp; &nbsp; &nbsp; Exit;<br>&nbsp; SetHookWnd(hw);<br>&nbsp; hNextMouseProc := SetWindowsHookEx(WH_MOUSE,<br>&nbsp; &nbsp; @MouseHookProc,<br>&nbsp; &nbsp; HInstance,<br>&nbsp; &nbsp; 0);<br>&nbsp; Result := hNextMouseProc &lt;&gt; 0;<br>end;<br><br>function UnInstallMouseHook: BOOL;stdcall;<br>begin<br>&nbsp; &nbsp; &nbsp; &nbsp; if hNextMouseProc &lt;&gt; 0 then<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; UnhookWindowshookEx(hNextMouseProc);<br>&nbsp; &nbsp; &nbsp; &nbsp; hNextMouseProc := 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; end;<br>&nbsp; Result := hNextMouseProc = 0;<br>end;<br><br><br><br>procedure DLlMain(dwReason: DWORD);<br>begin<br>&nbsp; &nbsp; &nbsp; &nbsp; case dwReason of<br>&nbsp; &nbsp; &nbsp; &nbsp; dll_process_Attach:<br>&nbsp; &nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; pGMem:=nil;<br>&nbsp; &nbsp; &nbsp; &nbsp; hObjHandle:=0;<br>&nbsp; &nbsp; &nbsp; &nbsp; MapMemory(sizeof(TShareData));<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; dll_process_Detach:<br>&nbsp; &nbsp; &nbsp; &nbsp; UnMapMemory;<br>&nbsp; end;<br>end;<br><br>Exports<br>&nbsp; &nbsp; &nbsp; &nbsp; InstallMouseHook,<br>&nbsp; UnInstallMouseHook,<br>&nbsp; SetHookWnd,<br>&nbsp; MouseHookProc;<br><br>begin<br>&nbsp; &nbsp; &nbsp; &nbsp; DLLProc :=@DLlMain;<br>&nbsp; DllMain(dll_Process_Attach);<br>end.<br><br>
 
对不起,jiangtao,你能不能提示一下你的例子?在你的程序里似乎共享的是一个指向<br>内存映射文件的指针,不同进程得到的确实是一样的,,但不知可否是其它的变量?<br>依我所见,该dll不过是将建立和释放内存映射文件的函数放进去罢了,似乎不用<br>那么复杂吧.客户端和服务端分别加进去就可以了.<br>
 
我的说法有误,该指针也不一定一样,只是用它能取得那块共享数据而已
 
是啊,关键在于用内存文件存放全局变量,才能实现多个应用程序<br>或进程共享,至于由谁建立和释放是无所谓的。<br>这个文件你可以把它想象成磁盘文件,只不过Win32提供了<br>System Page FIle功能可以印象到内存里。<br>文件的内容可以是任意值
 
很抱歉和你争了半天,可能是我和你的理解角度不同才照成的,我以为所谓的全局变量<br>是定义在dll里的,呵呵
 
另:版主我密码丢了,可不可以给我一下,我给你发了email
 
To qaz:<br>&gt;很抱歉和你争了半天,可能是我和你的理解角度不同才照成的,&gt;我以为所谓的全局变量<br>&gt;是定义在dll里的,呵呵<br>如果全局变量直接定义在DLL里面, 就需要只有VC才支持的共享数据段DLL连接方式,<br>但我试验了一下, 好像不太稳定, 内存映射文件好多了
 
啊,是啊,我错了,我忘了还有那个段,但那样做太危险了
 
我的初衷跟jiangtao 相同,只不过我将16位的和32位搞混了,<br>出来一大堆bug,其实这个问题还是相当有趣的,jiangtao 的exmple<br>写得很好啊,十万分感谢!!!<br>希望这个问题若有什么更优秀的做法,继续放在这里讨论。。。。<br>
 
我的初衷跟jiangtao 相同,只不过我将16位的和32位搞混了,<br>出来一大堆bug,其实这个问题还是相当有趣的,jiangtao 的exmple<br>写得很好啊,十万分感谢!!!<br>希望这个问题若有什么更优秀的做法,继续放在这里讨论。。。。<br>
 

Similar threads

I
回复
0
查看
607
import
I
I
回复
0
查看
698
import
I
I
回复
0
查看
462
import
I
I
回复
0
查看
442
import
I
顶部