《Inside C#》笔记(十五) 非托管代码 上

为确保为后兼容性,C#和.NET可以由此非托管的方法运行旧代码。非托管代码是乘无被.NET运行时管控的代码。非托管代码主要概括:平台调用服务(PlatformInvocation
Services)、不安全代码(Unsafe Code)、COM互操作(COM
interoperability)。

 

如出一辙
平台调用服务

平台调用服务(Platform
Invocation
Services)也于喻为PInvoke,可以采用非托管DLL中的不二法门、结构还是深受那传递回调函数。在动用非托管DLL前需先了解DLL内部方法的参数和归值。

a)基本用办法也:

 

图片 1

MessageBoxA属于Win32之API,需要事先声明一个及MessageBoxA的道签名一致的计,然后DllImport导入这个DLL,签名方法要用static
extern修饰。

 

b)签名方法也只是及DLL中之方法不同名,但得于DllImport的EntryPoint指定原始名称。

 

 

图片 2

 

c)使用CharSet

CharSet可以指定DLL所采用的字符集。比如上述的MessageBoxA实际上对应的凡Ansi编码,还有针对性承诺Unicode编码的MessageBoxW,除了直接指定调用哪个,还可用下面的写法:

 

图片 3

 

 

编译器会因CharSet的门类决定调用哪种MessageBox。这应该要DLL内部做相应匹配,至少要懂得每个MessageBox对应之字符集。

 

d)回调

不仅C#代码可以调用DLL的法门,DLL方法呢可用回调的章程使用C#代码。

 

这边以PrintWindow作为回调函数传递给了API中的EnumWindows方法。

 

图片 4

 

e)Marshal(排列、整理?)

于面前的事例中,DLL中MessageBox的不二法门参数为:

 

图片 5

 

 

C#代码中的法子签名并无同之了匹配,但却能够健康运行,这是因编译器自动进行了默认的Marshal,比如用C#的string类型对许为Win32的LPSTR。这个进程为得以手动进行,使用MarshalAs:

 

图片 6

 

倘要Marshal返回值,要记在方法体上面。

 

第二
编写不安全代码

此地的未安全代码指的凡不曾被.NET运行时托管的代码,内存的分红、释放、寻址等都无让拘束,比如可以C#代码中使用指针,在微场合C#指南针非常有因此,比如用调用C语言编写的API时、或者用对内存有完全的决定时。

a)与无安全代码相关的重中之重字unsafe和fixed

unsafe关键字用来告知.NET运行时,相关的代码块用非让托管。不让托管的代码块好是道、属性、或者是一个措施中的代码有。

fix关键字用来“钉”(pinning)住有对象,这样GC就不见面尝试对那回收了。但目标在内存的地址不见面被固定,地址仍然会叫周转时转,以避免出现内存碎片。因为地方不固定,所以这时用指针就要小心了。

b)在C#屡遭运用指针

C#遭到之指针比较异常:只能依靠为值类型、数组、字符串;如果指针指为数组,数组的首先只要素必须是值类型,因为指针实际上只要指向的凡以此数组的率先只要素;

C#着之指针相关的运算符与C、C++一样:&,取得某个对象的地点;
*,取得对象的值;
->,取得对象吃某个成员的价。简单示例为:

 

图片 7

 

 

编译标记为unsafe的代码前,需要在品种性质被安允许不安全代码。

 

读书材料:Inside C# by Tom Archer