有3个工程,MainExe.exe, FirstDll.dll, SecondDll.dllFirstDll.dll中有:
frmFirstForm: TfrmFirstForm (此窗体中放ADOQuery, DataSource, DBGrid连DataModule中的Connection显示一个表的数据)
DataModule: TDataModuleSecondDll.dll中有:
frmSecondForm: TfrmSecondForm(此窗体中放ADOQuery, DataSource, DBGrid连DataModule中的Connection显示一个表的数据)
DataModule: TDataModuleMainExe.exe中有:
MainForm: TMainForm
DataModule: TDataModule
------------------------------------
注意,以上3个工程中的DataModule文件其实是一个文件,只是在3个工程中都加入了其中.
MainForm导入一下函数
procedure ShowFirstForm; stdcall; external 'FirstDll.dll';
procedure CreateFirstDataModule; stdcall; external 'FirstDll.dll';
procedure ShowSecondForm; stdcall; external 'SecondDll.dll';
procedure CreateSecondDataModule; stdcall; external 'SecondDll.dll';启动MainExe程序,点Button1按钮,
procedure TMainForm.Button1Click(Sender: TObject);
begin
  CreateFirstDataModule;  //我想把此行语句删除,直接访问MainExe中的DataModule
  ShowFirstForm;
end;procedure TMainForm.Button2Click(Sender: TObject);
begin
  CreateSecondDataModule; //我想把此行语句删除,直接访问MainExe中的DataModule
  ShowSecondForm;
end;如果是这样写,程序没有问题,frmFirstForm和frmSecondForm都可以正常Show出,
而且其中的DbGrid也可以显示后台数据.可是现在的问题是: DataModule在FirstDll和SecondDll中都创建了一次,2个Dll
中分别建立了相同的Connection, 我想把CreateDataModule的动作放到MainExe中,
也就是说我想在主线程中创建一个Connection, 然后不管加入多少个Dll,都可以
使用这个Dll, 请问应该怎么做???? 
我试了只在MainExe中创建DataModule, 点Button1的时候抱Missing Connection or ConnectionString, Dll访问不到MainExe的DataModule!

解决方案 »

  1.   

    用個包把DATAMODULE放進去。DLL和EXE編譯時都帶上這個包編譯。或者傳遞一個結構類型的參數到DLL中
      

  2.   

    把ADOConnection作为参数传递。FirstDll.dll中:procedure ShowFirstForm(ado:TADOConnection);export;stdcall;
    begin
        Form1:=TForm1.Create(nil);
        Form1.ADOQuery1.Connection:=ado;
        Form1.ADOQuery1.SQL.Text:='select top 1 * from salesman';
        Form1.ADOQuery1.Open;
        Form1.Show;
    end;{$R *.res}
    exports
        ShowFirstForm;
    ..............SecondDll.dll中也类似定义处理。MainExe.exe中:procedure ShowFirstForm(ado:TAdoConnection); stdcall; external 'project1.dll';............
    DataModule上放自己的ADOConnection1    ShowFirstForm(DataModule.ADOConnection1);
        ShowSecondForm(DataModule.ADOConnection1);
      

  3.   

    给个思路给你吧。看到我这个结构的Conn吗,是一个自定义的结构,
    里面有很多自定义的对象,包括DataSet等。不过这个变量要定义在EXE中,
    把这个变量传入DLl就可以了。
    我的exe+dll就是用这种变量代替DM的。
    //------------------------------------------------------------------------------
    //定义主模块传递子模块系统参数结构
    //------------------------------------------------------------------------------
      PSysParamRec = ^TSysParamRec;
      TSysParamRec = record
        EmpId: Integer;                       //职员ID
        EmpCode: string;                      //职员编号
        EmpName: string;                      //职员姓名
        EmpPwd: string;                       //员工密码
        UserId: Integer;                      //用户ID
        UserCode: string;                     //用户编号
        UserName: string;                     //用户姓名
        UserPwd: string;                      //用户密码
        DptId: Integer;                       //所属部门ID
        DptCode: string;                      //所属部门编号
        DptName: string;                      //所属部门名称
        StockId: Integer;                     //所属仓库ID
        StockCode: string;                    //所属仓库编号
        StockName: string;                    //所属仓库名称
        ModId: Integer;                       //模块ID
        ModCode: string;                      //模块编号
        ModName: string;                      //模块名称
        MainTitle: string;                    //窗体的标题
        MainApp: TApplication;                //窗体的"TApplication"对象
        Conn: TADOConnection;                 //数据库连接组件
        SysSet: TSysSetRec;                   //系统参数设置
        InfoDbs: TInfoDbRec;                  //基础资料数据集         
      end;
      

  4.   

    各位,delphi中的exe和dll之間的對象共享不是那么簡單。只能達到有限共享,即共享虛方法。
    象2樓做法:通過傳遞指針,然后指定connection。這應該會造成地址訪問非法,因為會去訪問其中的數據成員(我沒有特地進行測試)。雖然地址是傳進了dll,但dll并無權限訪問exe內的對象數據。1、可采用1樓的做法,將dm等共用模塊放到bpl,bpl可達到“無縫鏈接”的效果;
    2、可以創建需要的connection,與原先做法相比,不需引用dm。但此做法將問題復雜化,還不如引用dm。
      

  5.   

    看到你說測試正常,我再看了下dataset的setconnection方法:
      if Connection <> Value then
      begin
        { At design time we require the dataset to be closed }
        if (csDesigning in ComponentState) then CheckInactive;
        { Set a flag that we can no longer requery if active }
        FConnectionChanged := Active;
        { Allow nil assignment while open for disconnected recordsets }
        if Active and (Value = nil) then
          RecordSet.Set_ActiveConnection(nil);
        if Assigned(Connection) then Connection.UnregisterClient(Self);
        if Assigned(Command) then Command.Connection := Value;
        if Assigned(Value) then
        begin
          Value.RegisterClient(Self);
          if Active and Assigned(Value.ConnectionObject) then
            RecordSet.Set_ActiveConnection(Value.ConnectionObject);
        end;
        if not (csLoading in ComponentState) then
          DataEvent(dePropertyChange, 0);
      end;
    注意這段
          Value.RegisterClient(Self);//虛方法,可通過
          if Active and Assigned(Value.ConnectionObject) then//active為false,應該馬上退出,不繼續執行
            RecordSet.Set_ActiveConnection(Value.ConnectionObject);
    照如上分析,應正常運行。關鍵是active為false,否則訪問value.connecobject,就會出錯。