.NET学习之路----我对P/Invoke技术的理解(一)
看了P/Invoke技术的介绍,于是想写下点东西,东西包含两个部分:知识的纪录和我的理解及疑问。
r托管代码中调用非托管API函数的过程
1、定位包含API的DLL;
2、载入DLL
3、找到DLL中想要的那个API,然后把参数压入栈中、排列数据(排列数据是什么意思?数据封送)
4、把执行权限从托管代码中转移到非托管代码中()
对Dll中的函数进行一些说明,以能调用
DllImport特性来说明函数,有一些特殊的作用,比如换掉API的原来名字,见DLLImport特性。
非托管函数和托管方法中数据类型对应:数据封送
把C#中数据转换成API中数据类型,是数据封送。对于每个 .NET Framework 类型均有一个默认非托管类型,公共语言运行库将使用此非托管类型在托管到非托管的函数调用中封送数据。string 类型默认非托管类型是LPTSTR,可以在非托管函数的 C# 声明中使用 MarshalAs 属性重写默认封送处理。例如:
[DllImport("msvcrt.dll")]
public static extern int puts(
[MarshalAs(UnmanagedType.LPStr)]
string m);
puts 函数的参数的默认封送处理已从默认值 LPTSTR 重写为 LPSTR
修改默认封送有什么用? 默认情况下,本机结构和托管结构在内存中的布局有所不同,因此,若要跨托管/非托管边界成功传递结构,需要执行一些额外步骤来保持数据的完整性。,
如果某个API中使用一个结构,那么C#中没有一个对应的托管类型与之对应的话,怎么办?需要为用户定义的结构指定自定义封送处理。
可以为传递到非托管函数或从非托管函数返回的结构和类的字段指定自定义封送处理属性。通过向结构或类的字段中添加 MarshalAs 属性可以做到这一点。还必须使用 StructLayout 属性设置结构的布局,还可以控制字符串成员的默认封送处理,并设置默认封装大小。
C++中:
struct SS
{ int a; byte b; }
对应C#中:
class SS
{
public int a;
public byte b;
}
封送,在此看来算是传数据,但是为什么要封送呢?封送是为了在托管内存和非托管内存中正常传递数据。?有时,出于对性能的考虑,会对托管结构的成员进行重新排列,因此有必要使用 StructLayoutAttribute 特性指示该结构为顺序布局。 将结构封装设置显式设置为与本机结构所使用的设置相同的设置也是一个好办法。
数据封送--基本数据类型对应关系:

数据封送中指针处理的两种情况 :
一、普通指针
在C#中使用ref out来实行封送。
二、Handle类型
C#中使用IntPtr来进行封送
封送,我的理解是两个方面,封装和传送。传送就像是方法中参数的传递那样;而封装就有些意思了,在封装前有时候需要做一些处理。就像是上面的 class SS和C++中的struct ss ,其实两者中的数据a、b在内存中是不一样的。详细如下:
class SS
{
public int a;
public byte b;
}
看起来a是在b的前面,其实在内存中可不是这样的,C#中类的字段成员的顺序在内存中是自动安排的,也就是说不像是源代码中那样,至于是为什么是自动(auto)安排顺序,还不知道,希望有人知道的话说一下,而在C++中类成员的顺序却是和看到的一样的,这就是为什么在封装前要做一些处理了,因为成员在内存中的顺序不一样!
C#中有一个特性可以调整这个顺序,也就是[StructLayout(LayoutKind.Sequential)],在没有显式进行修饰一个类时,默认情况下是[StructLayout(LayoutKind.Auto)]的。处理如下:
[StructLayout(LayoutKind.Sequential)]
class SS
{
public int a;
public byte b;
}
注册回调方法
遇到回调函数的处理。
.NET学习之路----我对P/Invoke技术的理解(一)的更多相关文章
- Qt 学习之路:模型-视图高级技术
PathView PathView是 QtQuick 中最强大的视图,同时也是最复杂的.PathView允许创建一种更灵活的视图.在这种视图中,数据项并不是方方正正,而是可以沿着任意路径布局.沿着同一 ...
- 1.typescirpt学习之路,*.d.ts和@types关系理解
今天看了看ts,文档上很多没用讲,小编疑惑了很久一个问题! *.d.ts和@types啥关系,小编查阅了很多文档,才弄明白. 首先,@types是npm的一个分支,我们把npm包发上去,npm包就会托 ...
- 微服务框架surging学习之路——序列化 (转载https://www.cnblogs.com/alangur/p/10407727.html)
微服务框架surging学习之路——序列化 1.对微服务的理解 之前看到在群里的朋友门都在讨论微服务,看到他们的讨论,我也有了一些自己的理解,所谓微服务就是系统里的每个服务都 可以自由组合.自由组 ...
- 『NiFi 学习之路』简介
『NiFi 学习之路』简介 『NiFi 学习之路』入门 -- 下载.安装与简单使用 『NiFi 学习之路』资源 -- 资料汇总 『NiFi 学习之路』把握 -- 架构及主要组件 『NiFi 学习之路』 ...
- RPC远程过程调用学习之路(一):用最原始代码还原PRC框架
RPC: Remote Procedure Call 远程过程调用,即业务的具体实现不是在自己系统中,需要从其他系统中进行调用实现,所以在系统间进行数据交互时经常使用. rpc的实现方式有很多,可以通 ...
- [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- jQuery学习之路(1)-选择器
▓▓▓▓▓▓ 大致介绍 终于开始了我的jQuery学习之路!感觉不能再拖了,要边学习原生JavaScript边学习jQuery jQuery是什么? jQuery是一个快速.简洁的JavaScript ...
- Android开发学习之路-RecyclerView滑动删除和拖动排序
Android开发学习之路-RecyclerView使用初探 Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析 Android开 ...
- webService学习之路(三):springMVC集成CXF后调用已知的wsdl接口
webService学习之路一:讲解了通过传统方式怎么发布及调用webservice webService学习之路二:讲解了SpringMVC和CXF的集成及快速发布webservice 本篇文章将讲 ...
随机推荐
- redis 集群热备自动切换sentinel配置实战
---恢复内容开始--- Redis SentinelSentinel(哨兵)是用于监控redis集群中Master状态的工具,其已经被集成在redis2.4+的版本中一.Sentinel作用:1): ...
- switch与ifelse的效率问题
switch...case与if...else的根本区别在于,switch...case会生成一个跳转表来指示实际的case分支的地址,而这个跳转表的索引号与switch变量的值是相等的.从而,swi ...
- Oracle 收缩数据文件
Oracle数据库中当某些大数据表不再需要的时候,我们可以通过以下方式来进行清理: DROP TABLE TBL_TEST PURGE; 但是对应表空间(tablespace)中的磁盘空间并没有得到释 ...
- 【原】CSS实现背景透明,文字不透明,兼容所有浏览器
11.11是公司成立的日子,16岁啦,我呢3岁半,感谢公司给了这样一个平台,让我得以学习和成长,这里祝愿公司发展越来越好~ 进入主题,每年11月11号是光棍节,产生于校园,本来只是一流传于年轻人的娱乐 ...
- Struts2 contentType属性列表
Struts2 contentType属性列表 博客分类: Struts 2 'ez' => 'application/andrew-inset', 'hqx' => 'applica ...
- 文件夹右键添加“DOS”命令
导入注册表 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Folder\shell\RunCMD] @="进入命令行&quo ...
- C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 基于数据库资源的多语言实现
以前的开发平台里,是用xml语言包实现了多语言功能,现在新的平台里进行了调整,把多语言包资源放在数据库表里实现了. 我们系统预留了多语言的配置全局变量.可以通过配置这个参数达到切换多语言的目的 我们在 ...
- C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 密码强化、网络安全强化
公司的系统庞大后,用户数量也庞大,容易引起各种网络安全相关问题,需要把每个用户的网络安全意识都提高,由于历史原因有些用户的密码过于简单,很容易被猜到,引起很多没必要的麻烦. 系统登录成功后,检查密码复 ...
- 如何使用eclipse打开已有工程
在开始使用Eclipse的时候,会发现一个问题,那就是如何打开一个现有的Eclipse工程,开始在菜单中找了好久也没找到. 其实,Eclipse生成的结果不像VC,Jcreator那样可以直接打开,若 ...
- 兼容firefox的 keyCode
<script language = "javascript"> document.onkeydown=inLogin function inLogin(e) { va ...