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

为了确定保证向后包容性,C#和.NET能够因此非托管的主意运行旧代码。非托管代码是指没有被.NET运维时管理控制的代码。非托管代码首要不外乎:平台调用服务(PlatformInvocation
Services)、不安全代码(Unsafe Code)、COM互操作(COM
interoperability)。

 


平台调用服务

平台调用服务(Platform
Invocation
Services)也被称作PInvoke,能够动用非托管DLL中的方法、结构照旧是给其传递回调函数。在采纳非托管DLL前需事先通晓DLL内部方法的参数和再次来到值。

a)基本接纳办法为:

 

C语言 1

MessageBoxA属于Win32的API,须求先声明一(Wissu)(Beingmate)个与MessageBoxA的法子签名一致的法子,然后DllImport导入这些DLL,签名方法必须用static
extern修饰。

 

b)签名方法也可与DLL中的方法不相同名,但需在DllImport的EntryPoint内定原始名称。

 

 

C语言 2

 

c)使用CharSet

CharSet能够内定DLL所运用的字符集。比如上述的MessageBoxA实际上对应的是Ansi编码,还有对应Unicode编码的MessageBoxW,除了直接钦定调用哪个,还可用上面包车型客车写法:

 

C语言 3

 

 

编写翻译器会基于CharSet的连串决定调用哪类MessageBox。那应当供给DLL内部做相应匹配,至少需求明白各类MessageBox对应的字符集。

 

d)回调

不仅C#代码能够调用DLL的方法,DLL方法也可用回调的法子使用C#代码。

 

此间将PrintWindow作为回调函数字传送递给了API中的EnumWindows方法。

 

C语言 4

 

e)Marshal(排列、整理?)

在前边的例证中,DLL中MessageBox的章程参数为:

 

C语言 5

 

 

C#代码中的方法签名并没有与之完全匹配,但却能健康运行,那是因为编写翻译器自动实行了私下认可的马尔斯hal,比如将C#的string类型对应为Win32的LPST汉兰达。这几个历程也能够手动进行,使用MarshalAs:

 

C语言 6

C语言, 

假若要马尔斯hal再次来到值,要标记在方法体上面。

 


编写不安全代码

此间的不安全代码指的是从未有过被.NET运维时托管的代码,内部存款和储蓄器的分配、释放、寻址等都不受约束,比如能够在C#代码中使用指针,在有点场地C#指南针非凡有用,比如必要调用C语言编写的API时、恐怕供给对内部存储器有完全的控制时。

a)与不安全代码相关的机要字unsafe和fixed

unsafe关键字用来告知.NET运营时,相关的代码块将不接受委托管。不受托管的代码块能够是办法、属性、或然是四个办法内部的代码片段。

fix关键字用来“钉”(pinning)住某些对象,那样GC就不会尝试对其回收了。但指标在内部存款和储蓄器的地点不会被一定,地址还是会被周转时浮动,以幸免出现内部存款和储蓄器碎片。因为地址不稳定,所以这时候使用指针就要小心了。

b)在C#中应用指针

C#中的指针比较尤其:只好指向值类型、数组、字符串;假若指针指向数组,数组的首先个因素必须是值类型,因为指针实际上要指向的是以此数组的第2个成分;

C#中的指针相关的运算符与C、C++一样:&,取得某些对象的地点;
*,取得对象的值;
->,取得对象中有个别成员的值。容易示例为:

 

C语言 7

 

 

编写翻译标记为unsafe的代码前,需求在档次性质中设置允许不安全代码。

 

上学资料:Inside C# by Tom Archer