例:
  有两个应用分别为app1, app2, 他们都加载了同一个dll: sharelib.dll 。 
  在Sharelib.dll 中导出一个函数 为 function GetListObj:TList; 返回一个list对象,也就是List的指针。函数内容大概为
  ----------
  var
   g_List:TList;
  
  function GetListObj:TList; stdcall;
  begin
    //没有就创建
    if not Assigned(g_List) then
       g_List := TList.Create;
 
    resutl := g_List;
  end;
  -----------
  这时app1 程序用这个dll函数GetListObj返回的List对象,使用List的add方法 ,app2程序中使用此函数得到的对应可以读取到app1中添加的内容。
 
  如何能实现这个效果,请高手指教一下。 我看到有VC中可以使用
-------------
  #pragma data_seg("Shared")
  std::list <User_Info> SrvSockList;
  std::list <User_Info>::iterator pSockList;
  SOCKET m_Listensock=0;
  HWND g_hWnd = NULL; 
  #pragma data_seg()
  #pragma comment(linker, "/Section:Shared,rws") 
------------
我想delphi也应该有办法的

解决方案 »

  1.   

    我公司软件几个版本的都是动态调用一个dll的,这样实现有什么问题?
    只要在各个工程的搜索路径指向同一个dll单元。
      

  2.   

    楼上的没理解我的意思, 我的意思是这个dll是多个程序共享,dll中的数据也共享。
    我上面说的可能还有些不完整, 通过getListobj返回的list对像,应该只能读不能写
    要写入的话,应使用dll中的函数,比如 function additem(student:PStudent);
    dll中的大概写法
    ---
    function additem(student:PStudent);
    var
      pStudent:PStudent;
    begin
      getmem(pStudent,sizeof(TStudent));
      copyMemory(pStudent, student, sizeof(sizeof(TStudent)));
      g_List.add(pStudent);
    end; 
    这样写是让内存是dll分配的,加载他的dll都能共享到它的内存
    -----
    ---------
      一个学生结构体
      PStudent = ^TStudent;
      TStudent = record
        ID:integer;//学号
        age:integer;//年龄
        name:array[0..32] of char;//姓名
      end
    -----------
    我在app1.exe中
    procedure fun();
    var
      st:TStudent;
    begin
      st.id := 1;
      st.name ='aaa';
      st.age = 20;
      
      additem(@st);  //这里使用上面的dll中的additem函数来添加数据。
    end;效果是在app2.exe中使用getlistobj也能读取到上面的的st.id=1,st.name='aaa'这个数据
      

  3.   

    两个进程,不同的地址空间,只是用同一个dll应该不行.可以用楼上说的内存映射.
      

  4.   

    用内存映射,下面是我写的一段代码给你参考。{****************************************************************************}
    {                                                                            }
    {       SharedMem.pas
    {       Comment:真正的实现了服务和应用程序共享内存
    {                                                                            }
    {****************************************************************************}unit MsgSharedMem;interfaceuses
      Windows, Messages, SysUtils, Math;const
      CSharedMemSize = 1024*1024*3;
      CSharedMemName = 'Global\FleetReportSharedMemorty';  WM_CreateReport = WM_USER + 1001;         
      WM_EndReport = WM_USER + 1002;            
      CSocketEndTag = #13#10;type
      //报表执行状态
      TReportState = (rsFinished, rsInexistent, rsWaiting, rsRunning, rsException, rsCanceled);
      TShareMem = record
        Handle: THandle;                           
        ReportID: Integer;                         
        ReportState: TReportState;                 
        ReportType: Integer;                          
        StatFile: array[0..1024*1024] of Char;     
        TestConfig: array[0..1024*1024] of Char;   
        MapFile: array[0..1024*100] of Char;       
        SiteData: array[0..1024*100] of Char;      
        DestFile: array[0..1024*2] of Char;        
        HintMsg: array[0..1024*3] of Char;         
      end;
      PShareMem = ^TShareMem;  TPublicVars = class
      private
        FShareMem: PShareMem;
        FMapFile: THandle;
        procedure SetHandle(AValue: THandle);
        function GetHandle: THandle;
        procedure SetReportID(AValue: Integer);
        function GetReportID: Integer;
        procedure SetReportState(AValue: TReportState);
        function GetReportState: TReportState;
        procedure SetReportType(AValue: Integer);
        function GetReportType: Integer;
        procedure SetStatFile(AValue: string);
        function GetStatFile: string;
        procedure SetTestConfig(AValue: string);
        function GetTestConfig: string;
        procedure SetMapFile(AValue: string);
        function GetMapFile: string;
        procedure SetSiteData(AValue: string);
        function GetSiteData: string;
        procedure SetDestFile(AValue: string);
        function GetDestFile: string;
        procedure SetHintMsg(AValue: string);
        function GetHintMsg: string;
      public
        constructor Create(ANew: Boolean);
        destructor Destroy; override;
        property Memory: PShareMem read FShareMem;
        property Handle: THandle read GetHandle write SetHandle;
        property ReportID: Integer read GetReportID write SetReportID;
        property ReportState: TReportState read GetReportState write SetReportState;
        property ReportType: Integer read GetReportType write SetReportType;
        property StatFile: string read GetStatFile write SetStatFile;
        property TestConfig: string read GetTestConfig write SetTestConfig;
        property MapFile: string read GetMapFile write SetMapFile;
        property SiteData: string read GetSiteData write SetSiteData;
        property DestFile: string read GetDestFile write SetDestFile;
        property HintMsg: string read GetHintMsg write SetHintMsg;
      end;implementation{ TPublicVars }
    resourcestring
      CouldNotMapViewOfFile = 'Could not map view of file.';const
      SECURITY_NULL_SID_AUTHORITY = 0;
      SECURITY_WORLD_SID_AUTHORITY = 1;
      SECURITY_LOCAL_SID_AUTHORITY = 2;
      SECURITY_CREATOR_SID_AUTHORITY = 3;
      SECURITY_NT_AUTHORITY = 5;  SECURITY_NULL_RID = 0;
      SECURITY_WORLD_RID = 0;
      SECURITY_LOCAL_RID = 0;
      SECURITY_CREATOR_OWNER_RID = 0;
      SECURITY_CREATOR_GROUP_RID = 1;  ACL_REVISION = 2; type
      ACL_SIZE_INFORMATION = record
        AceCount: DWORD;
        AclBytesInUse: DWORD;
        AclBytesFree: DWORD;
      end;  ACE_HEADER = record
        AceType: BYTE;
        AceFlags: BYTE;
        AceSize: WORD;
      end;
      PACE_HEADER = ^ACE_HEADER;  ACCESS_ALLOWED_ACE = record
        Header: ACE_HEADER;
        Mask: ACCESS_MASK;
        SidStart: DWORD;
      end;          constructor TPublicVars.Create(ANew: Boolean);
    var
      SecMem: SECURITY_ATTRIBUTES;
      aSD: SECURITY_DESCRIPTOR;
    begin
      inherited Create;
      { 创建一个任何用户都可以访问的内核对象访问权 }
      InitializeSecurityDescriptor(@aSD, SECURITY_DESCRIPTOR_REVISION);
      SetSecurityDescriptorDacl(@aSD, True, nil, False);
      SecMem.nLength := SizeOf(SECURITY_ATTRIBUTES);
      SecMem.lpSecurityDescriptor := @aSD;
      SecMem.bInheritHandle := False;
      FMapFile := CreateFileMapping($FFFFFFFF, @SecMem, PAGE_READWRITE, 0, CSharedMemSize, CSharedMemName);
      FMapFile := OpenFileMapping(File_Map_All_Access, False, CSharedMemName);
      if (FMapFile = 0) then
      begin
        raise Exception.Create(SysErrorMessage(GetLastError));
        OutputDebugString(PChar(SysErrorMessage(GetLastError)));
      end
      else
      begin                                   // 成功
        FShareMem := MapViewOfFile(FMapFile, File_Map_All_Access, 0, 0, CSharedMemSize);
        OutputDebugString(PChar(SysErrorMessage(GetLastError) + ',Handle=' + IntToStr(Handle)));
      end;
    end;
      

  5.   


    destructor TPublicVars.Destroy;
    begin
      UnmapViewOfFile(FShareMem);
      CloseHandle(FMapFile);
      inherited;
    end;function TPublicVars.GetHandle: THandle;
    begin
      Result := FShareMem.Handle;
    end;procedure TPublicVars.SetHandle(AValue: THandle);
    begin
      FShareMem.Handle := AValue;
    end;function TPublicVars.GetReportID: Integer;
    begin
      Result := FShareMem.ReportID;
    end;procedure TPublicVars.SetReportID(AValue: Integer);
    begin
      FShareMem.ReportID := AValue;
    end;function TPublicVars.GetReportType: Integer;
    begin
      Result := FShareMem.ReportType;
    end;procedure TPublicVars.SetReportType(AValue: Integer);
    begin
      FShareMem.ReportType := AValue;
    end;function TPublicVars.GetStatFile: string;
    begin
      Result := FShareMem.StatFile;
    end;procedure TPublicVars.SetStatFile(AValue: string);
    var
      iMaxCount: Integer;
    begin
      ZeroMemory(@FShareMem.StatFile[0], Length(FShareMem.StatFile));
      iMaxCount := Min(Length(FShareMem.StatFile), Length(AValue));
      StrMove(@FShareMem.StatFile[0], PChar(AValue), iMaxCount);
    end;function TPublicVars.GetTestConfig: string;
    begin
      Result := FShareMem.TestConfig;
    end;procedure TPublicVars.SetTestConfig(AValue: string);
    var
      iMaxCount: Integer;
    begin
      ZeroMemory(@FShareMem.TestConfig[0], Length(FShareMem.TestConfig));
      iMaxCount := Min(Length(FShareMem.TestConfig), Length(AValue));
      StrMove(@FShareMem.TestConfig[0], PChar(AValue), iMaxCount);
    end;procedure TPublicVars.SetMapFile(AValue: string);
    var
      iMaxCount: Integer;
    begin
      ZeroMemory(@FShareMem.MapFile[0], Length(FShareMem.MapFile));
      iMaxCount := Min(Length(FShareMem.MapFile), Length(AValue));
      StrMove(@FShareMem.MapFile[0], PChar(AValue), iMaxCount);
    end;function TPublicVars.GetMapFile: string;
    begin
      Result := FShareMem.MapFile;
    end;function TPublicVars.GetSiteData: string;
    begin
      Result := FShareMem.SiteData;
    end;procedure TPublicVars.SetSiteData(AValue: string);
    var
      iMaxCount: Integer;
    begin
      ZeroMemory(@FShareMem.SiteData[0], Length(FShareMem.SiteData));
      iMaxCount := Min(Length(FShareMem.SiteData), Length(AValue));
      StrMove(@FShareMem.SiteData[0], PChar(AValue), iMaxCount);
    end;function TPublicVars.GetDestFile: string;
    begin
      Result := FShareMem.DestFile;
    end;procedure TPublicVars.SetDestFile(AValue: string);
    var
      iMaxCount: Integer;
    begin
      ZeroMemory(@FShareMem.DestFile[0], Length(FShareMem.DestFile));
      iMaxCount := Min(Length(FShareMem.DestFile), Length(AValue));
      StrMove(@FShareMem.DestFile[0], PChar(AValue), iMaxCount);
    end;function TPublicVars.GetHintMsg: string;
    begin
      Result := FShareMem.HintMsg;
    end;procedure TPublicVars.SetHintMsg(AValue: string);
    var
      iMaxCount: Integer;
    begin
      ZeroMemory(@FShareMem.HintMsg[0], Length(FShareMem.HintMsg));
      iMaxCount := Min(Length(FShareMem.HintMsg), Length(AValue));
      StrMove(@FShareMem.HintMsg[0], PChar(AValue), iMaxCount);
    end;      function TPublicVars.GetReportState: TReportState;
    begin
      Result := FShareMem.ReportState;
    end;procedure TPublicVars.SetReportState(AValue: TReportState);
    begin
      FShareMem.ReportState := AValue;
    end;end.
      

  6.   

    用内存映射文件共享Dll中的数据
    具体楼主可以下载一个 <delphi 5 开发人员指南> 第九章 里面有详细介绍,还有实例,看过后保证会
      

  7.   

    建议使用一个中间的EXE,配置为单个实例。其它进程通过DCOM的方式与该EXE完成公用对象的访问。
      

  8.   

    非常感谢Bear_hx 的代码,在你的代码中,主要是对一个TShareMem进行共享,对一个固定的内存段使用内存映射我知道,而我想实现是对N个相同结构的数据共享,这些数据是放到一个容器中,这些数据对像可能随时被创建或消毁。是不是在每次在被创建都要使用CreateFileMapping呢? 还是有很多不解!
      

  9.   

    顶 内存映射文件。。
    #pragma data_seg("Shared") 
    是VC的使用方法,Delphi不能这么用。解决方案是建立内存映射文件
    或者可以使用汇编,形成obj文件,再由Delphi连接编译。
    可以参照:
    http://www.delphibbs.com/delphibbs/dispq.asp?lid=3088031
      

  10.   

    我想使用内存映射的方法似乎很解决。 
    我在说明一下实现的效果。
    这是一个多层的框架分为:数据库(各种数据库或配置文件)、中间层业务(dll或能共享数据的东西)、界面层(可执行程序用于显示、输入、输出)1. 界面层应用程序A运行:加载了中间层dll2. 中间层dll读取数据库或配置文件, 生成对应的内存数据结构,用链表或树容器来管理,具有查找添加、删除、修改等操作.
       dll会导出这些操作函数。3. 界面层A调用dll的函数显示出对应的数据。 4. 界面层B程序,也加载dll,发现这些容器对像已经创建就不在读数据库或配置(相似一个单件模式),显示出的数据与A程序一样。5. 程序A,修改了一个数据。 程序B先前会设置一个回调函数到dll中,dll响应一个OnDataChange事件,B程序会生新刷新界面,到dll中读取新的数据。
    unsigned 你说的DCOM我不太了解,能详细点吗?能推介些资料或书籍吗?
      

  11.   

    unsigned 我查了一下Delphi DCOM 只能操作数据库中的数据,如果能应用到程序中的数据结构中了。
    比如说我现在有一种数据结构:
    一个链表,装了一个结构体有两个字段:一个是SerIP,另个还是连表,这个连表里装了一个结构体里面有clientIP,计算机名
    IP List
    |192.168.1|list|------->|192.168.1.100|计算机1|
    |192.168.2|list|         |192.168.1.101|计算机2| 
    |192.168.3|list|
      

  12.   

    为DCOM的对象添加一个方法,然后在客户端调用该方法即可。
      

  13.   

    你这种要求还是按僵哥说的,采用DCOM共享吧。
      

  14.   

    unsigned 我对dcom还是不太会用, 我想返回一个自己的对象类型怎么做了, 就如上面那个IP管理的数据结构,他是一个类。有添加删除等方法,我想的是客户端取得服务器这个对象,通过操作这个对象就能控制服务器上的数据。
    我开始想,是不是要所有的类都要有一个SaveToData的方法,把这个类中的数据定义成一段连续的内存段,然后通过指针返回到客户端,客户端用LoadFromData的方法来还原。但是这样做觉得很复杂了,所有的对象都要这样定义。
      

  15.   

    我写了一个示例,演示多进程共享同一个StringList,然后通过Name和Value关联,从而各进程之间通过同样的Name得到一致的Value.
    http://download.csdn.net/source/824285
      

  16.   

    unit UnitManagedObject;interfaceuses
        Windows
      ;
    type
      TManagedObject = class(TObject)
        {Management Properties}
        private
          FManagementCount  : Integer;      //对象引用计数
        public
          {structor}
          constructor Create;
        public
          {Management}
          procedure Free;
          function Attach:TManagedObject;
          function Detach: Integer;
      end;
    implementation{TManagedBaseObject}
      {structor}
      constructor TManagedObject.Create;
      begin
        Inherited Create;
        FManagementCount := 1;
      end;  {Management}
      function TManagedObject.Attach  : TManagedObject;
      begin
        Result := Nil;
        if InterlockedIncrement(FManagementCount) = 1 then
          begin
            InterlockedDecrement(FManagementCount);
            Exit;
          end;
        Result := self;
      end;  function TManagedObject.Detach  : Integer;
      begin
        Result := InterlockedDecrement(FManagementCount);
      end;  procedure TManagedObject.Free;
      begin
        if Detach>0 then
          Exit;
        Inherited;
      end;end.
      

  17.   

    unsigned 你好非常谢谢你, 你上传的资源我没有积分,下载不了。你能在QQ上发给我吗?
    我的QQ号是:6346289
      

  18.   

    http://forum.csdn.net/PointForum/Forum/PointExchange.aspx