zoukankan      html  css  js  c++  java
  • DLL对象类型转换

    //以下代码是错误的!!!
    //这一节主要告诉大家,以这种方式进行开发dll是不对的以及错误原因,正确的方式是什么!
    //DLL内创建对象,并把对象返回
    function GetDataSet(str,conn:PChar): TADODataSet;stdcall; 
    begin 
      Result:=TADODataSet.Create(nil); 
      Result.Close; 
      Result.ConnectionString:=conn; 
      Result.CommandText:= str; 
      try 
          Result.Open; 
      except 
        on E:Exception do 
        begin 
            ShowMessage(E.Message); 
            GetDataSet:=nil; 
        end; 
      end; 
    end; 
    //主调程序
    var 
      datas:TADODataSet; 
      sql,conn:string; 
      i:Integer; 
    begin 
      sql:='select ....'; 
      conn:='Provider=SQLOLEDB.1;Password=sa;Persist Security Info=True;User ID=sa;Initial Catalog=Master'; 
        datas:=GetDataSet(PChar(sql),PChar(conn));//如果单纯返回一个对象,这样没问题,但要注意的是不要进行类型转换(这里的类型转换包括显式或隐式类型转换)
        try 
            DBGridEh1.DataSource.DataSet:=datas; 
    //上面这句话就出错了,原因如下:
    //导致错误的原因为RTTI转换导致地址不一致的问题!
    dbgrid.datasource.dataset:=datas;
    datas是TADODataset类型,由于是一个的地址是从dll传出至主调中,在赋值前是一个隐式的向上转型的过程(Dataset<--TADODataSet),这时会调用Is 、As等System单元的函数,仔细看一下Is与As的实现(IsClass、InheritedFrom),不难发现在转换过程中把dll中的RTTI转换为application中的RTTI,造成地址不一致,转换错误!
    为什么地址不一致呢?
    因为dll与exe维护着各自的的RTTI表,位于PE文件头下方的的Code段(不清楚的朋友可看一下Win32的进程布局),如主调与dll中都有Dataset对象,在进程装载时先将主进程中的RTTI载入,地址为ox00611000,而dll载入时dll内的dataset类层次不可能为ox00611000,可能是ox00722000,而这时在主调或dll中转换时,Delphi是对RTTI中记录的各个类进行地址判断,如果相同,则直接将地址赋值,如果不同,则递归性地找其父类地址,如果其父类地址还是找不到,则会提示错误,很显然,地址肯定是不一样的!
    解决方法:
    如果实在想共享对象,并有可能在主调或dll中进行转型怎么办?
    答:用bpl,当使用bpl时,bpl与主调共用一个RTTI,这样就没有转型的问题了!
        except 
          on E:Exception do 
          begin 
            ShowMessage(E.Message); 
          end; 
      end; 
    View Code
  • 相关阅读:
    BZOJ 3506 机械排序臂 splay
    BZOJ 2843 LCT
    BZOJ 3669 魔法森林
    BZOJ 2049 LCT
    BZOJ 3223 文艺平衡树 splay
    BZOJ 1433 假期的宿舍 二分图匹配
    BZOJ 1051 受欢迎的牛 强连通块
    BZOJ 1503 郁闷的出纳员 treap
    BZOJ 1096 ZJOI2007 仓库设计 斜率优化dp
    BZOJ 1396: 识别子串( 后缀数组 + 线段树 )
  • 原文地址:https://www.cnblogs.com/key-ok/p/3358871.html
Copyright © 2011-2022 走看看