|
分享源码
界面截图: |
|
是否带模块: |
纯源码 |
备注说明: |
- |
偶然有兴致,研究了一下易语言的一些变量内存格式
https://bbs.125.la/forum.php?mod=viewthread&tid=14232322
但是有个问题一直没搞懂:就是汇编取自定义数据类型地址然后传递给API调用时,会异常
后来搞了个调用CallNtPowerInformation函数读取CPU频率信息的功能,我又想到了自定义数据类型的问题
昨晚再次研究了一下发现,我以前的思路就是错的...因为我在【DLL命令定义表】的参数传指提示中发现了这句话:
某些实际Dll库命令的参数需要接收数据地址,设置本属性为真可以确保将参数数据的地址传递过去。如果参数数据的类型为数组、文本、字节集、用户定义数据类型、库定义数据类型,则无论此属性是否为真,都将传递数据地址。如果本属性为真且调用 Dll 命令时所传递过来数据的类型与相应位置处所定义参数的数据类型不一致但可以相互转换,则系统先分配一段临时内存空间,然后进行转换并将转换后的数据存放到该空间,最后将此内存空间的地址传递到实际的 Dll 库命令。
反正这意思就是,易语言会将数组啊、自定义数据类型那些东西,在调用API的时候二次封装,调用API结束后再给一个个成员赋值回来。
所以嘛,本文章就是给新手讲解一下易语言的数组、自定义数据类型在易语言内存中的格式以及调用API时是怎么转换的。
为了方便查看,就用json格式来展示吧:
{
"数组变量栈指针":{
"+4":"数组成员数",
"+8":"数组指针"
},
"易语言数组指针":{
"数组成员0":[{
"数据类型成员0指针":"数据类型成员0内容"
},{
"数据类型成员1指针":"数据类型成员1内容"
},{
"数据类型成员2指针":"数据类型成员2内容"
}],
"数组成员1":[{
"数据类型成员0指针":"数据类型成员0内容"
},{
"数据类型成员1指针":"数据类型成员1内容"
},{
"数据类型成员2指针":"数据类型成员2内容"
}],
"数组成员2":[{
"数据类型成员0指针":"数据类型成员0内容"
},{
"数据类型成员1指针":"数据类型成员1内容"
},{
"数据类型成员2指针":"数据类型成员2内容"
}]
},
"调用API时转换成一段字节集(四字节对齐的)":"数据类型成员0,数据类型成员1,数据类型成员2,数据类型成员0,数据类型成员1,数据类型成员2,数据类型成员0,数据类型成员1,数据类型成员2"
}
比如说我们调用API,传递了这个数据类型
易语言在调用时会自动打包一个格式:成员a内容+成员b内容+成员c指针 所以一共是传递了3*4=12字节的数据+字节集指针指向的堆内存
我们操作变量指针第一步其实只需要获取变量栈内存地址,别人封装的其它数据类型那些其实无非就是增加了一些指针的加减操作罢了
比如,文本型指针只需要读栈内存指向的地址即可,字节集指针需要读栈内存指向的堆内存地址+8,+8是因为易语言这样定的格式
指针到整数(指针_取变量地址(字节集)+4) = 字节集长度 指针到整数(指针_取变量地址(字节集)+8)=字节集数据
有许许多多的骚操作都是玩指针实现的,可能平时用不到,但是这知识我认为是必须掌握的
多一份知识,在面对同一个问题时就会多一份方案,这样就可以根据自己的经验来判断哪种方案最合适
顺便提一下,我仔细研究了一下发现,易语言应该是不适合直接用指针方式“复制”变量的,最多做到交换变量指针(栈指向的堆内存)
而且数据类型要匹配,否则100%的内存泄露...目前没有什么完美的方案能够读取易语言的自定义数据类型,更别提复制了。
CallNtPowerInformation.e
(10.56 KB, 下载次数: 92)
|
评分
-
查看全部评分
|