欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-05-18 23:01:40
托管代码 托管代码(Managed Code)实际上就是中间语言(IL)代码。代码编写完毕后进行编译,此时编译器把代码编译成中间语言(IL),而不是能直接在你的电脑上运行的机器码。程序集(Assembly)的文件负责封装中间语言,程序集中包含了描述所创建的方法、类以及属性的所有元数据。托管代码在公共 ......
.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 函数都是非托管代码的示例。

区别:

     1、托管代码是一种中间语言,运行在clr上;

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

     2、托管代码独立于平台和语言,能更好的实现不同语言平台之间的兼容;

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

     3、托管代码可享受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一下,然后调用对应的方法即可。