《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,需要事先声明一个暨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#代码中之不二法门签名并不曾同的完全匹配,但却能够健康运转,这是为编译器自动进行了默认的Marshal,比如将C#的string类型对诺为Win32底LPSTR。这个历程也得手动进行,使用MarshalAs:

 

C++ 6

 

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

 

第二
编写不安全代码

此地的未安全代码指的是尚未被.NET运行时托管的代码,内存的分配、释放、寻址等都无受约,比如可以当C#代码中应用指针,在稍微场合C#指南针非常有因此,比如要调用C语言编写的API时、或者用对内存有完全的决定时。

a)与匪安全代码相关的显要字unsafe和fixed

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

fix关键字用来“钉”(pinning)住某对象,这样GC就非会见尝试对那回收了。但目标在内存的地点不会见为定位,地址仍然会吃运行时别,以避免出现内存碎片。因为地址不固定,所以这用指针就要小心了。

b)在C#遭到动用指针

C#受到的指针比较独特:只能拄于值类型、数组、字符串;如果指针指为数组,数组的率先只要素必须是值类型,因为指针实际上只要本着的是以此数组的率先单要素;

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

 

C++ 7

 

 

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

 

学学资料:Inside C# by Tom Archer