【转,整理】C# 非托管代码

.Net Framework 是由彼此独立又相关的两部分组成:CLR 和 类库, CLR是它为咱们提供的服务,类库是它实现的功能.
.NET的大部分特性----垃圾收集,版本控制,线程管理等,都使用了CLR提供的服务

托管代码数据库

 

托管代码(Managed Code)实际上就是中间语言(IL)代码。代码编写完毕后进行编译,此时编译器把代码编译成中间语言(IL),而不是能直接在你的电脑上运行的机器码。程序集(Assembly)的文件负责封装中间语言,程序集中包含了描述所建立的方法、类以及属性的全部元数据。
托管代码在公共语言运行库(CLR)中运行。CLR提供了一个实时编译器,用来把IL代码编译为本机机器代码.这样一来,CLR可以使代码变得可移植,由于.NET应用程序的源代码必须被编译为IL代码,这些IL代码能够运行在任何提供CLR服务的平台上.从CLR的角度来看,全部的语言都是平等的,只要有一个能生成IL代码的编译器就行,这就确保了各类语言的互操性.编程

非托管代码安全

公共语言运行库环境的外部,由操做系统直接执行的代码。非托管代码必须提供本身的垃圾回收、类型检查、安全支持等服务,它与托管代码不一样,后者从公共语言运行库中得到这些服务,而非托管代码是在运行库以外运行的代码。例如COM 组件、ActiveX 接口和 Win32 API 函数都是非托管代码的示例。网络

区别:app

     一、托管代码是一种中间语言,运行在CLR上;编程语言

          非托管代码被编译为机器码,运行在机器上。函数

     二、托管代码独立于平台和语言,能更好的实现不一样语言平台之间的兼容;布局

          非托管代码依赖于平台和语言。ui

     三、托管代码可享受CLR提供的服务(如安全检测、垃圾回收等),不须要本身完成这些操做;编码

          非托管代码须要本身提供安全检测、垃圾回收等操做。

.net的堆就是托管堆.没有非托管堆.引用类型的引用目标就是在堆里.

值类型的值就在栈里.

所谓的系统资源.是指:网络链接,数据库链接.文件流.这种东西.

这里的托管就是指被CLR管理,托管堆就是被CLR管理的堆。非托管资源须要手动释放,托管资源由GC帮你打理。

using能够跟踪非托管资源周期内的活动,一旦发现非托管资源生命结束了,就会强制调用dispose方法去释放在该做用域的非托管资源的内存。

C#如何直接调用非托管代码,一般有2种方法:

1.  直接调用从 DLL 导出的函数。

2.  调用 COM 对象上的接口方法

从dll中导出函数:

a.使用 C# 关键字 static 和 extern 声明方法。

b.将 DllImport 属性附加到该方法。DllImport 属性容许您指定包含该方法的DLL 的名称。

c.若是须要,为方法的参数和返回值指定自定义封送处理信息,这将重写 .NET Framework 的默认封送处理。

using System;

using System.Runtime.InteropServices;

    public class MSSQL_ServerHandler

    {

        [DllImport("kernel32.dll")]

        public static extern int GetShortPathName

        (

            string path,

            StringBuilder shortPath,

            int shortPathLength

)

     }

DllImportAttribute 的字段

 

字段

说明

BestFitMapping

启用或禁用最佳匹配映射。

CallingConvention

指定用于传递方法参数的调用约定。默认值为 WinAPI,该值对应于基于 32 位 Intel 的平台的 __stdcall。

CharSet

控制名称重整以及将字符串参数封送到函数中的方式。默认值为 CharSet.Ansi。

EntryPoint

指定要调用的 DLL 入口点。

ExactSpelling

控制是否应修改入口点以对应于字符集。对于不一样的编程语言,默认值将有所不一样。

PreserveSig

控制托管方法签名是否应转换成返回 HRESULT 而且返回值有一个附加的 [out, retval] 参数的非托管签名。

默认值为 true(不该转换签名)。

SetLastError

容许调用方使用 Marshal.GetLastWin32Error API 函数来肯定执行该方法时是否发生了错误。在 Visual Basic 中,默认值为 true;在 C# 和 C++ 中,默认值为 false。

ThrowOnUnmappableChar

控件引起的异常,将没法映射的 Unicode 字符转换成一个 ANSI"?"字符。

 

 

 

StructLayoutAttribute类

在C/C++中,struct类型中的成员的一旦声明,则实例中成员在内存中的布局(Layout)顺序就定下来了,即与成员声明的顺序相同,而且在默认状况下老是按照结构中占用空间最大的成员进行对齐(Align);固然咱们也能够经过设置或编码来设置内存对齐的方式.在.net托管环境中,CLR提供了更自由的方式来控制struct中Layout:咱们能够在定义struct时,在struct上运用StructLayoutAttribute特性来控制成员的内存布局

 

C#提供了一个StructLayoutAttribute类,经过它你能够定义本身的格式化类型,在受管辖代码中,格式化类型是一个用StructLayoutAttribute说明的结构或类成员,经过它可以保证其内部成员预期的布局信息。布局的选项共有三种:

布局选项  
描述  
LayoutKind.Automatic  
为了提升效率容许运行态对类型成员从新排序。  
注意:永远不要使用这个选项来调用不受管辖的动态连接库函数。  
LayoutKind.Explicit  
对每一个域按照FieldOffset属性对类型成员排序  
LayoutKind.Sequential  
对出如今受管辖类型定义地方的不受管辖内存中的类型成员进行排序。

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)]

 

 

COM interop具体操做:

a. 用atl写com服务程序

b. 使用Tlbimp将atl写的com程序转换成 COM DLL

   用以下命令:

   tlbimp 你写的com.dll

   tlbimp是 .NETFramework SDK中附带的类型库导入程序。用这个命令便是把生成一个非托管com dll的托管包装。

c. 托管客户端很是简单

   直接new一下,而后调用对应的方法便可。