子模块采用DLL方式调用,其中带入DLL中的有TAdodsOp和TGlobal公共变量参数,(AHandle: THandle; AdoServer: TAdoDsOp; AGlobal: TGlobal)--详细参数情况
TAdodsOp和TGlobal带入后采用内存映射方式进行调用。现问题是:
1、若两个系统同时调用这个DLL时,会报地址冲突错误,经跟踪,是刷新数据集时报错。
2、单个系统在调用DLL或退出时,也会偶儿报一些地址错错误。请大虾帮忙看下,这问题该如何解决?
以下是内存映射使用方式:
unit uMemMap;interfaceuses windows, sysutils, uadoDsOp, uGlobal, Forms, ActiveX;const
  VirtualFile1 = 'HS_ADOSERVER_SHAREDLL';
  VirtualFile2 = 'HS_GLOBAL_SHAREDLL';
  DataSize1 = sizeof(TAdoDsOp);
  DataSize2 = sizeof(TGlobal);var
  hMapFile1: THandle;
  hMapFile2: THandle;  //------------------------------------------
  _AdoServer: ^TAdoDsOP; //必须使用内存映射文件
  _Global: ^TGlobal;
  _OldHandle: THandle;  
implementationinitialization  CoInitialize(nil);
  //使用内存映射文件来共享接口
  
  //创建AdoServer接口的内存映射文件
  hMapFile1 := CreateFileMapping($FFFFFFFF, nil,Page_ReadWrite, 0, DataSize1, VirtualFile1);
  if hMapFile1 = 0 then
  begin
    raise Exception.Create ('创建IAdoDsOP内存映射文件错误!');
    Application.Terminate;
  end;
  _AdoServer := MapViewOfFile (hMapFile1, File_Map_Write, 0, 0, DataSize1);  //创建Global类的内存映射文件
  hMapFile2 := CreateFileMapping($FFFFFFFF, nil,Page_ReadWrite, 0, DataSize2, VirtualFile2);
  if hMapFile2 = 0 then
  begin
    raise Exception.Create ('创建Global类内存映射文件错误!');
    Application.Terminate;
  end;
  _Global := MapViewOfFile (hMapFile2, File_Map_Write, 0, 0, DataSize2);finalization
  
  UnmapViewOfFile(_AdoServer);
  UnMapViewOfFile(_Global);  
  CloseHandle(hMapFile1);
  CloseHandle(hMapFile2);
  CoUninitialize;
end.以下是带入参数使用方式:
procedure ShowCard(AHandle: THandle; AdoServer: TAdoDsOp; AGlobal: TGlobal; ACardNo, AMonth: PChar; ADataType: integer); stdcall;
var
  AOldHandle: THandle;
begin  _AdoServer^ := AdoServer;
  _Global^ := AGlobal;
AOldHandle := Application.Handle;

application.Handle := AOldHandle;
end;

解决方案 »

  1.   

    补充错误代码:
      Access violation at address 0391C110. Read of address 039C110.
        Access violation at Address 06FEC110. Read of address 06FEC11.
        Access violation at address 0413E4A5 in module 'name.dll'. Read at address 03E9582C.
        Access violation at address 0398E4A5 in module 'name.dll'. Read of address 03E2582C.
      

  2.   

    两个系统调用同一个DLL发生地址报错的问题采用PAGE_WRITECOPY参数已解决了。具体如下:
      hMapFile1 := CreateFileMapping($FFFFFFFF, nil,PAGE_WRITECOPY, 0, DataSize1, VirtualFile1);
      if hMapFile1 = 0 then
      begin
        raise Exception.Create ('创建IAdoDsOP内存映射文件错误!');
        Application.Terminate;
      end;
      _AdoServer := MapViewOfFile (hMapFile1, FILE_MAP_COPY, 0, 0, DataSize1);现另一个DLL偶儿会报地址错的问题,不知会不会因这错误的解决而解决,有待考证。
      

  3.   

    经再次测试,DLL偶儿性报错还是会出现,特别是关闭一个DLL再打开另一个DLL后会报错。这问题还希望大虾帮忙给予指导下
      

  4.   

    1 FileMaping创建的时候使用最大权限
    2 无论如何,你都不能够使用FileMapping来共享接口,因为不同进程的地址空间都是独立的,是不能共享的,除非你只共享数据.
    3 如果不是特别必要,不要随意修改Application
    4 你确实要共享接口,你可以使用com,用一个automation的exe服务器来创建接口.
      

  5.   

    to:muroachanf
    能否说明清楚一些?或是解决办法?
      

  6.   

    这问题还是没得到解决,muroachanf能否说得详细一些?
    准备结贴了。
      

  7.   

    就是说不同的进程,是不能用指针来共享接口的,这个是做不到的,除非你向Midas或者Automation的Exe一样,模拟一个接口调用出来,如果是dll之间,那恐怕都是不现实的,你虽然可以用filemapping来共享内存区,但是,你仍然不能共享他们本身的内存,除非所有关于接口调用的代码,数据都在共享内存区(这个显然不可能),所以你的方法本身就不对.正确的做法是提供一个Automation或者Midas服务器,它们的原理都一样,区别在于其中Midas支持网络,然后从服务器上请求一个一个接口,再调用这个接口就好了.
      

  8.   

    不管怎么样,结贴了。
    谢谢muroachanf的回复