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;
DLL对象类型转换的更多相关文章
- java对象类型转换和多态性
html { font-family: sans-serif } body { margin: 0 } article,aside,details,figcaption,figure,footer,h ...
- C# new关键字和对象类型转换(双括号、is操作符、as操作符)
一.new关键字 CLR要求所有的对象都通过new来创建,代码如下: Object obj=new Object(); 以下是new操作符做的事情 1.计算类型及其所有基类型(一直到System.Ob ...
- Object类和对象类型转换
学习内容:Object类和对象类型转换 一.Object类 1.Object类是所有类的父类,是Java类层中最高层的类. 2.getClass()方法:返回对象执行时的Class实例,然后用此实例调 ...
- C#调用C++的DLL 数据类型转换
/C++中的DLL函数原型为 //extern "C" __declspec(dllexport) bool 方法名一(const char* 变量名1, unsig ...
- C# 调用C++ DLL 的类型转换
//C#调用C++的DLL搜集整理的所有数据类型转换方式,可能会有重复或者多种方案,自己多测试 //c++:HANDLE(void *) ---- c#:System.IntPtr //c++:Byt ...
- [转载] C# 调用C++ DLL 的类型转换
//C#调用C++的DLL搜集整理的所有数据类型转换方式,可能会有重复或者多种方案,自己多测试 //c++:HANDLE(void *) ---- c#:System.IntPtr //c++:Byt ...
- C#——调用C++的DLL 数据类型转换
/C++中的DLL函数原型为 //extern "C" __declspec(dllexport) bool 方法名一(const char* 变量名1, unsig ...
- C# 调用C++ DLL 的类型转换(转载版)
最近在做视频监控相关的demo开发,实现语言是C#,但视频监控的SDK是C++开发的,所以涉及到C#调用C++的dll库.很多结构体.参数在使用时都要先进行转换,由非托管类型转换成托管类型后才能使用. ...
- java之对象类型转换
基本数据类型之间的转换: 自动类型转换:小的数据类型可以自动转换成大的数据类型: 强制类型转换:可以把大的数据类型转换成小的数据类型:float = (float)32.0; public class ...
随机推荐
- [转]SSH反向连接及Autossh
http://www.cnblogs.com/eshizhan/archive/2012/07/16/2592902.html SSH反向连接及Autossh 0.接触Linux恐怕对SSH再熟悉不过 ...
- lava.lang.String数据转换为java.sql.Date
在JavaWeb编程中,往往涉及数据库,javaBean,前端数据数据类型不一致的问题 数据库和javaBean之间可以直接选择相对应的数据类型,而serverlet从前端获取的数据往往是String ...
- github上DQN代码的环境搭建,及运行(Human-Level Control through Deep Reinforcement Learning)conda配置
最近师弟在做DQN的实验,由于是强化学习方面的东西,正好和我现在的研究方向一样于是我便帮忙跑了跑实验,于是就有了今天的这个内容. 首先在github上进行搜寻,如下图: 发现第一个星数最多,而且远高于 ...
- Python之路,第一篇:Python入门与基础
第一篇:Python入门与基础 1,什么是python? Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. 2,python的特征: (1)易于学习,易于利用: (2)开 ...
- Codeforces Round #516(Div 2)
比赛链接:传送门 A. Make a triangle!(简单思维) 题目大意: 给你三条边,问你最多加多少长度能使这三条边能构成三角形. 思路: 最大边小于答案加另外两条边的和. #include ...
- manjaro初体验
manjaro Linux是https://distrowatch.com/网站上排名第一的Linux分支. https://manjaro.org/ 选择,下载,打开主页下载页:https://ma ...
- fedora的选择
Fedora 首页包含3种版本: 工作站,服务器,ATOMIC 个人只要使用工作站即可,然后,下载界面有另一个选择:Silverblue ========================== Silv ...
- EnableAutoConfiguration注解的工作原理(org.springframework.boot.autoconfigure.EnableAutoConfiguration=core.bean.MyConfig)
EnableAutoConfiguration注解的工作原理(org.springframework.boot.autoconfigure.EnableAutoConfiguration=core.b ...
- AangularJS相关术语
1. 数据模型对象(model object)是指$scope对象.$scope对象又是一个简单的JavaScript对象,其中的属性可以被视图访问,也可以同控制器进行交互. 2. $scope ...
- cdcq的独立博客上线辣!-> http://cdcq.coding.me/blog/
cdcq的独立博客上线辣!-> http://cdcq.coding.me/blog/ 这个博客会逐渐停更 独立博客被硬盘保护吃掉了,直到省选前独立博客应该不会再上线 (如果没进队就永远不会上线 ...