《Inside C#》笔记(十五) 非托管代码 上
为了保证向后兼容性,C#和.NET可以通过非托管的方式运行旧代码。非托管代码是指没有被.NET运行时管控的代码。非托管代码主要包括:平台调用服务(PlatformInvocation Services)、不安全代码(Unsafe Code)、COM互操作(COM interoperability)。
一 平台调用服务
平台调用服务(Platform Invocation Services)也被称作PInvoke,可以使用非托管DLL中的方法、结构甚至是给其传递回调函数。在使用非托管DLL前需事先了解DLL内部方法的参数和返回值。
a)基本使用方法为:
MessageBoxA属于Win32的API,需要先声明一个与MessageBoxA的方法签名一致的方法,然后DllImport导入这个DLL,签名方法必须用static extern修饰。
b)签名方法也可与DLL中的方法不同名,但需在DllImport的EntryPoint指定原始名称。
c)使用CharSet
CharSet可以指定DLL所使用的字符集。比如上述的MessageBoxA实际上对应的是Ansi编码,还有对应Unicode编码的MessageBoxW,除了直接指定调用哪个,还可用下面的写法:
编译器会根据CharSet的类型决定调用哪种MessageBox。这应该需要DLL内部做相应配合,至少需要知道每个MessageBox对应的字符集。
d)回调
不仅C#代码可以调用DLL的方法,DLL方法也可用回调的方式使用C#代码。
这里将PrintWindow作为回调函数传递给了API中的EnumWindows方法。
e)Marshal(排列、整理?)
在前面的例子中,DLL中MessageBox的方法参数为:
C#代码中的方法签名并没有与之完全匹配,但却能正常运行,这是因为编译器自动进行了默认的Marshal,比如将C#的string类型对应为Win32的LPSTR。这个过程也可以手动进行,使用MarshalAs:
如果要Marshal返回值,要标记在方法体上面。
二 编写不安全代码
这里的不安全代码指的是没有被.NET运行时托管的代码,内存的分配、释放、寻址等都不受约束,比如可以在C#代码中使用指针,在有些场合C#指针非常有用,比如需要调用C语言编写的API时、或者需要对内存有完全的控制时。
a)与不安全代码相关的关键字unsafe和fixed
unsafe关键字用来告知.NET运行时,相关的代码块将不受托管。不受托管的代码块可以是方法、属性、或者是一个方法内部的代码片段。
fix关键字用来“钉”(pinning)住某个对象,这样GC就不会尝试对其回收了。但对象在内存的地址不会被固定,地址仍然会被运行时浮动,以避免出现内存碎片。因为地址不固定,所以这时使用指针就要小心了。
b)在C#中使用指针
C#中的指针比较特殊:只能指向值类型、数组、字符串;如果指针指向数组,数组的第一个元素必须是值类型,因为指针实际上要指向的是这个数组的第一个元素;
C#中的指针相关的运算符与C、C++一样:&,取得某个对象的地址; *,取得对象的值; ->,取得对象中某个成员的值。简单示例为:
编译标记为unsafe的代码前,需要在项目属性中设置允许不安全代码。
学习资料:Inside C# by Tom Archer
《Inside C#》笔记(十五) 非托管代码 上的更多相关文章
- 《Inside C#》笔记(十五) 非托管代码 下
二编写不安全代码 a)fixed关键字 代码中体现了fixed的用法:fixed (type* ptr= expression) { …}:type是类似int*这样的非托管类型或void类型,exp ...
- python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...
- 使用Typescript重构axios(二十五)——文件上传下载进度监控
0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...
- 学习ASP.NET Core Razor 编程系列十五——文件上传功能(三)
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- (C/C++学习笔记) 十五. 构造数据类型
十五. 构造数据类型 ● 构造数据类型概念 Structured data types 构造数据类型 结构体(structure), 联合体/共用体 (union), 枚举类型(enumeration ...
- How tomcat works 读书笔记十五 Digester库 上
Digester库 在前面的几个章节里,我们对tomcat里各个组件的配置完全是使用写硬编码的形式完成的. 如 Context context = new StandardContext(); Loa ...
- MySQL学习笔记十五:优化(2)
一.数据库性能评测关键指标 1.IOPS:每秒处理的IO请求次数,这跟磁盘硬件相关,DBA不能左右,但推荐使用SSD. 2.QPS:每秒查询次数,可以使用show status或mysqladmin ...
- 【慕课网实战】Spark Streaming实时流处理项目实战笔记十五之铭文升级版
铭文一级:[木有笔记] 铭文二级: 第12章 Spark Streaming项目实战 行为日志分析: 1.访问量的统计 2.网站黏性 3.推荐 Python实时产生数据 访问URL->IP信息- ...
- (转载)西门子PLC学习笔记十五-(数据块及数据访问方式)
一.数据块 数据块是在S7 CPU的存储器中定义的,用户可以定义多了数据块,但是CPU对数据块数量及数据总量是有限制的. 数据块与临时数据不同,当逻辑块执行结束或数据块关闭,数据块中的数据是会保留住的 ...
随机推荐
- 关于@font-face的使用
以前在写网页的时候,总是使用浏览器默认的字体,因此从未使用过@font-face,然而,最近在做官网的时候,UI规定了字体,要在所有浏览器下都展现同一效果.多番查询下,发现@font-face用起来是 ...
- ajax无刷新技术
第一步:创建ajax引擎 var xmlhttp=""; if(window.XMLHttpRequest){ xmlhttp=new XMLHttpRequest(); }els ...
- oracle中常见的对表、表空间和视图的操作
创建表:create table t1(key1 type default 0,key2 type not null) 删除表:drop table t1; 删除表数据:truncate table ...
- android底部菜单栏的编写
开发工具android stdio,组件Radio Button 1.新建空项目DDDD 2.将事先准备好的图标复制到对应的文件夹中(如图),这五个文件夹都要拷进去,图标文件http://pan.ba ...
- HTML页面自动跳转,windows操作
1) html的实现 <head> <!-- 以下方式只是刷新不跳转到其他页面 --> <meta http-equiv="refresh" cont ...
- dart之旅(二)- 内建类型
目录 number 类型 字符串 布尔类型 像大多数语言一样,dart 也提供了 number,string,boolean 等类型,包括以下几种: numbers strings booleans ...
- Spring Boot - 修改Tomcat默认的8080端口
前言 默认情况下,Spring Boot内置的Tomcat服务会使用8080端口启动,我们可以使用以下任何技巧去更改默认的Tomcat端口: 注:我们可以通过server.port=0配置,去自动配置 ...
- Java集合类常见面试知识点总结
微信公众号[Java技术江湖]一位阿里Java工程师的技术小站 Java集合类学习总结 这篇总结是基于之前博客内容的一个整理和回顾. 这里先简单地总结一下,更多详细内容请参考我的专栏:深入浅出Java ...
- C++ 单例模式实现
#include <iostream> #include <mutex> std::mutex mtx; class Singleton { private: Singleto ...
- apache伪静态配置(URL重写)
1.打开apache配置文件 httpd.conf .2.开启rewrite模块,去掉注释# #LoadModule rewrite_module modules/mod_rewrite 3.让apa ...