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

<本文来源互联网摘要>
在.net 编制程序环境中,系统的能源分为托管财富和非托管财富。

集身体语言言运营库利用StructLayoutAttribute控制类或结构的数额字段在托管内部存储器中的物理布局,即类或结构需求按某种格局排列。假诺要将类传递给急需钦赐布局的非托管代码,则显式控制类布局是重大的。它的构造函数中用
LayoutKind值开始化 StructLayoutAttribute 类的新实例。
LayoutKind.Sequential 用于强制将成员按其现出的次第举办逐一布局。

1      DLLImport的使用

 

using System;

using System.Runtime.InteropServices; //命名空间

class Example

{

//用DllImport 导入Win32的MessageBox函数

    [DllImport(“user32.dll”, CharSet = CharSet.Unicode)]

public static extern int MessageBox(IntPtr hWnd, String text, String
caption, uint type);

//方法被声称为 static。那是 P/Invoke 方法所供给的,因为在该 Windows API
中向来不//1致的实例概念。接下来,还要注意该措施被标记为
extern。那是引玉之砖编写翻译器该方式是通//过二个从 DLL
导出的函数完毕的,因而不需求提供方法体。

    static void Main()

    {

        // Call the MessageBox function using platform invoke.

        MessageBox(new IntPtr(0), “Hello World!”, “Hello Dialog”, 0);

    }

}

应用非托管DLL函数并不困难,上面大家能够详细的打听上面的代码的意思。首先介绍怎么样是托管代码,什么是非托管代码。然后再详尽介绍DLLImport的运用方法和各字段的意义。

托管代码

  对于托管的财富的回收工作,是不须要人工干预回收的,而且你也无能为力干预他们的回收,所能够做的

StructLayout天性允许大家决定Structure语句块的因素在内部存款和储蓄器中的排列情势,以及当那些因素被传送给外部DLL时,运行库排列这个要素的主意。

贰      托管代码 (managed code)

.NET
Framework的中坚是其运维库的履行环境,称为公共语言运转库(CLLAND)或.NET运营库。平日将在CL兰德QX56的决定下运作的代码称为托管代码(managed
code)。

运行库环境(而不是直接由操作系统)执行的代码。托管代码应用程序能够获得公共语言运营库服务,例如自动垃圾回收、运转库类型检查和晋城补助等。这几个劳动帮扶提供单身于阳台和语言的、统1的托管代码应用程序行为。

  托管代码是能够使用20各个协助Microsoft .NET
Framework的高级语言编写的代码,它们包罗:C#, J#, Microsoft Visual
Basic .NET, Microsoft JScript .NET,
以及C++。全部的言语共享统1的类库集合,并能被编码成为中等语言(IL)。运维库编写翻译器(runtime-aware
ompiler)在托管执行环境下编写翻译中间语言(IL)使之成为地点可实施的代码,并采纳数组边界和目录检查,万分处理,垃圾回收等手段保险项目标安全。

 

  在托管执行环境中运用托管代码及其编写翻译,能够幸免过多优秀的造成安全黑洞和不平稳程序的编程错误。同样,许多不可靠的宏图也自行的被增加了安全
性,例如类型安检,内部存款和储蓄器管理和刑满释放解除劳教无效对象。程序员能够花更多的生气关切程序的应用逻辑设计并能够减去代码的编写量。那就代表更加短的耗费时间和更健
壮的主次。

 

简易点说,托管代码是microsoft的高级中学级语言,他根本的成效是在.NET
FRAMEWO奥迪Q7K的CL途乐执行代码前去编写翻译源代码,也正是说托管代码充当着翻译的成效,源代码在运维时刻为多个阶段:

  1.源代码编写翻译为托管代码;(所以源代码能够有诸各类,如VB,C#,J#)

  二.托管代码编译为microsoft系统的.net平台专用文件(如类库、可执行文件等)。

 

只是领悟.net
CLLX570怎么办这几个操作。也正是说对于你的应用程序创设的绝超过六壹%对象,能够依靠
.NET

 

贰.一     非托管代码 (unmanaged code)

  在公私语言运维库环境的表面,由操作系统直接实施的代码。非托管代码必须提供本人的垃圾回收、类型检查、安全辅助等劳务;它与托管代码区别,后者从公共语言运转库中收获那么些劳动。

.net中托管代码的意义

托管代码(Managed
Code)实际上正是中档语言(IL)代码。代码编写完结后进行编写翻译,此时编写翻译器把代码编译成人中学间语言(IL),而不是能直接在您的处理器上运营的机器码。程序集(Assembly)的文本负责打包中间语言,程序集中包括了描述所成立的艺术、类以及质量的有所元数据。
托管代码在集体语言运转库(CL帕杰罗)中运转。CL奥德赛提供了二个实时编译器,用来把IL代码编写翻译为本机机器代码.这样1来,CL奥迪Q三能够使代码变得可移植,因为.NET应用程序的源代码必须被编写翻译为IL代码,那个IL代码能够运作在其余提供CLCRUISER服务的阳台上.从CL卡宴的角度来看,具有的语言都以如出1辙的,只要有二个能生成IL代码的编写翻译器就行,那就确认保障了各个语言的互操性.

Framework 的杂质回收器隐式地执行全数须要的内部存款和储蓄器管理职分。托管代码正是基于.net元数据格式的代码,
运作于.net平台之上,全体的与操作系统的交流有.net来完结,就好像把那么些功用委托给.net,所以称为托管代码。

 

二.二     什么是托管?托管是何许看头?

托管代码正是基于.net元数据格式的代码,运维于.net平台之上,全体的与操作系统的交流有.net来完结,就好像把那个功用委托给.net,所以称为托管代码。非托管代码则相反。

举个例子l

Vc.net还足以应用mfc,atl来编写程序,他们基于MFC或然ATL,而不是.NET,所以是非托管代码,假使基于.net比如C#,VB.net则是托管代码

非托管代码是指.NET解释不了的

简短的说,托管代码的话,.net能够活动释放资料,非托管代码要求手动释放资料.

怎么样是托管C++

托管是.NET的1个专门概念,它提倡1种新的编制程序理念,由此大家一齐能够把“托管”视为“.NET”。由托管概念所引发的C++应用程序包涵托管代码、托管数据和托管类多个组成都部队分。

托管代码

.Net环境提供了好多骨干的运作(RUNTIME)服务,比如11分处理和安全策略。为了能利用那些劳动,须要求给运营环境提供部分音信代码(元数
据),那种代码正是托管代码。全数的C#、VB.NET、JScript.NET默许时都以托管的,但Visual
C++私下认可时不是托管的,必须在编写翻译器中利用命令行选项(/CLLAND)才能生出托管代码。

托管数据

与托管代码密切相关的是托管数据。托管数据是由国有语言运转的废品回收器进行分配和刑满释放解除劳教的数额。暗许意况下,C#、Visual
Basic 和 JScript.NET 数据是托管数据。不过,通过动用特殊的要害字,C#
数据足以被标记为非托管数据。Visual
C++数据在私下认可情形下是非托管数据,就算在接纳 /CL宝马X5 开关时也不是托管的。

托管类

尽管Visual
C++数据在默许情状下是非托管数据,可是在使用C++的托管增加时,能够使用“__gc”关键字将类标志为托管类。就好像该名称所展现的那么,它意味着类实
例的内存由垃圾回收器管理。其它,三个托管类也全然能够改为 .NET
框架的积极分子,由此能够推动的功利是,它可以与任何语言编写的类正确地拓展交互操作,如托管的C++类能够从Visual
Basic类继承等。但还要也有局地限制,如托管类只可以从3个基类继承等。

非托管代码

举个例子l 

能够通过System.Runtime.InteropServices.StructLayout  
天性精确的支配每二个组织成员的职务。
System.Runtime.InteropServices.StructLayout  
允许的值有StructLayout.Auto   StructLayout.Sequential  
StructLayout.Explicit.
    
壹.Sequential,顺序布局,比如
struct
S1
{
  int a;
  int b;
}
那么暗中认可情形下在内部存款和储蓄器里是先排a,再排b
也正是如若能取到a的地址,和b的地址,则离开一个int类型的长短,4字节
[StructLayout(LayoutKind.Sequential)]

二.3     托管代码怎样调用非托管代码(c sharp怎么样调用c++代码)?

三种常用的做法:

下载:

  1. COM interop

具体操作:

a. 用atl写com服务程序

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

   用如下命令:

   tlbimp 你写的com.dll

   tlbimp是 .NET Framework
SDK中附带的类型库导入程序。用这么些命令就是把生成三个非托管com
dll的托管包装。

c. 托管客户端分外不难

   直接new一下,然后调用对应的章程即可。

  1. P/Invoke

a. 在托管客户端扩充一条 DllImport语句和1个方法的调用。

介绍二个P/Invoke网站,

以此网址根本是2个wiki,允许开发者发现,编辑,扩充PInvoke的署名,用户自定义类型和从托管代码(指c#和VB.net开发语言)访问win32和别的非托管api的新闻。

世界外市的.Net开发者能够很简单享受温馨有价值的东西给社区,

在集体语言运转库条件的外部,由操作系统间接执行的代码。非托管代码非得提供温馨的废品回收、类型检查、安全援救等服务,它与托管代码分裂,后者从公物语言运营库中取得那个劳动,而非托管代码是在运维库之外运转的代码。例如COM
组件、ActiveX 接口和 Win3二 API
函数都以非托管代码的示例。

 

struct S1
{
  int a;
  int
b;
}
这样和上3个是同等的.因为私下认可的内部存款和储蓄器排列正是Sequential,也正是按成员的先后顺序排列.
贰.Explicit,精确布局
急需用菲尔德Offset()设置每一种成员的职位
如此就能够实现类似c的公用体的机能
[StructLayout(LayoutKind.Explicit)]

二.4     托管代码和非托管代码功能的对峙统壹

在场原版的书文 来自

更详细的音信

区别:

Vc.net还足以使用mfc,atl来编写程序,他们依照MFC恐怕ATL,而不是.NET,全部是非托管代码,若是基于.net比如C#,VB.net则是托管代码

struct S1
{
  [FieldOffset(0)]
  int a;
  [FieldOffset(0)]
   int b;
}
那般a和b在内部存款和储蓄器中地址壹样

3      DllImportAttribute 的字段

在对托管代码举行 P/Invoke 调用时,DllImportAttribute
类型扮演着首要的剧中人物。DllImportAttribute 的显要作用是给 CLCRUISER 提醒哪个 DLL
导出您想要调用的函数。相关 DLL 的名称被看作三个构造函数参数字传送递给
DllImportAttribute。

下表列出了具有与平台调用相关的特征字段。
对于种种字段,下表都将涵盖其暗中同意值,并且会提供3个链接,用于获取有关怎么着使用那个字段定义非托管
DLL 函数的消息。

字段

说明

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"?"字符。

 

除此之外提出宿主 DLL 外,DllImportAttribute
还富含了部分可选属性,当中多个专门有趣:EntryPoint、CharSet、SetLastError
和 CallingConvention。
/3877783_84071078.shtml

     一、托管代码是1种中间语言,运维在CL奥迪Q伍上;

 

 

3.1     entrypoint

入口点用于标识函数在 DLL
中的地方。在托管对象中,指标函数的原名或序号入口点将标识跨越交互操作边界的函数。其余,您能够将入口点映射到一个不等的名目,那实质上是将函数重命名。

以下列出了重命名 DLL 函数的只怕原因:

·        防止接纳分别轻重缓急写的 API 函数名

·        符合现行反革命的命名标准

·        提供使用不一样数据类型的函数(通过表明同1 DLL 函数的三个本子)

·        简化对含有 ANSI 和 Unicode 版本的 API 的运用

 

你能够动用
DllImportAttribute.EntryPoint
字段按名称或序号钦命 DLL 函数。假诺函数在情势定义中的名称与入口点在 DLL
的称谓一致,则不用用 EntryPoint
字段来显式地方统一标准识函数。不然,使用以下属性形式之1来提醒名称或序号:

l  [DllImport(“dllname”, EntryPoint=”Functionname”)]

l  [DllImport(“dllname”, EntryPoint=”#123″)]

l  钦定入口点名称时,您能够提供一个字符串来提醒包括入口点的 DLL
的名称,也许也得以按序号来标识入口点。序号以 # 符号为前缀,如
#一。假诺省略此字段,则集体语言运营库将动用以DllImportAttribute
标记的 .NET 方法的名号。

非托管代码,系统调用使用详解。上边的示范演示怎么样运用 EntryPoint 字段将代码中的 MessageBoxA 替换为
MsgBox

using System.Runtime.InteropServices;

public class Win32 {

    [DllImport(“user32.dll”, EntryPoint=”MessageBoxA”)]

    public static extern int MsgBox(int hWnd, String text, String
caption, uint type);

}    

          非托管代码被编写翻译为机器码,运转在机械上。

非托管代码是指.NET解释不了的 

 

3.2     CharSet

以下来自

DllImportAttribute.CharSet
字段控制字符串封送处理并规定平台调用在 DLL
中查找函数名的不2秘诀。本大旨将介绍那二种表现。

对此利用字符串参数的函数,有个别 API 将导出它们的七个版本:窄版本 (ANSI)
和宽版本 (Unicode)。例如,Win3二 API 包罗 MessageBox
函数的以下入口点名称:

·        MessageBoxA

提供单字节字符 ANSI 格式,其特征是在入口点名称后附加三个“A”。对
MessageBoxA 的调用始终会以 ANSI 格式封送字符串,它广泛于 Windows 九五和 Windows 九八 平台。

·        MessageBoxW

提供双字节字符 Unicode 格式,其特性是在入口点名称后附加3个“W”。对
MessageBoxW 的调用始终会以 Unicode 格式封送字符串,它宽广于 Windows
NT、Windows 两千 和 Windows XP 平台。

CharSet 字段接受以下值:

CharSet.Ansi(默认值)

·        字符串封送处理

平台调用将字符串从托管格式 (Unicode) 封送为 ANSI 格式。

·        名称相称


DllImportAttribute.ExactSpelling
字段为 true(它是 Visual Basic 二〇〇七中的默许值)时,平台调用将只搜索您钦点的称呼。例如,假设钦赐MessageBox金沙注册送58 ,,则平台调用将搜索
MessageBox,就算它找不到完全相同的拼写则战败。

ExactSpelling 字段为 false(它是 C++ 和 C#
中的暗许值)时,平台调用将第二搜索未处理的别称(MessageBox),借使找不到未处理的别称,则将追寻已处理的名称
(MessageBoxA)。请留心,ANSI 名称相称行为与 Unicode
名称相称行为分歧。

CharSet.Unicode

·        字符串封送处理

阳台调用会将字符串从托管格式 (Unicode) 复制为 Unicode 格式。

·        名称相称

ExactSpelling 字段为 true(它是 Visual Basic 二零零五中的暗中同意值)时,平台调用将只搜索您内定的称呼。例如,假使钦点MessageBox,则平台调用将搜索
MessageBox,即便它找不到完全相同的拼写则失利。

ExactSpelling 字段为 false(它是 C++ 和 C#
中的默许值)时,平台调用将首先搜索已处理的名称
(MessageBoxW),若是找不到已处理的称号,则将寻找未处理的别称(MessageBox)。请留意,Unicode 名称相称行为与 ANSI 名称相配行为分歧。

CharSet.Auto

·        平台调用在运转时依据目的平台在 ANSI 和 Unicode
格式之间展开分选。

上边包车型大巴以身作则演示用于内定字符集的 MessageBox
函数的八个托管定义。在率先个概念中,通过简单,使 CharSet 字段暗中同意为
ANSI 字符集。

[DllImport(“user32.dll”)]

public static extern int MessageBoxA(int hWnd, String text, String
caption, uint type);

[DllImport(“user32.dll”, CharSet=CharSet.Unicode)]

public static extern int MessageBoxW(int hWnd, String text, String
caption, uint type);

[DllImport(“user32.dll”, CharSet=CharSet.Auto)]

public static extern int MessageBox(int hWnd, String text, String
caption, uint type);

CharSet.Ansi 和 CharSet.Unicode 的名号相称规则大不一致。对于 Ansi
来说,假使将 EntryPoint
设置为“MyMethod”且它存在的话,则赶回“MyMethod”。假如 DLL
中绝非“MyMethod”,但存在“MyMethodA”,则赶回“MyMethodA”。对于 Unicode
来说则正好相反。借使将 EntryPoint
设置为“MyMethod”且它存在的话,则赶回“MyMethodW”。若是 DLL
中不设有“MyMethodW”,但存在“MyMethod”,则赶回“MyMethod”。假若运用的是
Auto,则格外规则与平台有关(在 Windows NT 上为 Unicode,在 Windows 九八上为 Ansi)。借使 ExactSpelling 设置为 true,则唯有当 DLL
中留存“MyMethod”时才回来“MyMethod”。

假使 DLL 函数不以任何措施处理文件,则能够忽略 DllImportAttribute 的
CharSet 属性。不过,当 Char 或 String 数据是等式的一片段时,应该将
CharSet 属性设置为 CharSet.Auto。那样能够使 CL汉兰达 依照宿主 OS
使用方便的字符集。如若未有显式地安装 CharSet 属性,则其私下认可值为
CharSet.Ansi。那几个暗中同意值是有缺点的,因为对于在 Windows 贰仟、Windows XP
和 Windows NT® 上展开的 interop
调用,它会被动地震慑文本参数封送处理的性质。

应该显式地选用 CharSet.Ansi 或 CharSet.Unicode 的 CharSet 值而不是选取CharSet.Auto
的唯壹情状是:您显式地内定了二个导出函数,而该函数特定于那二种 Win3二 OS
中的某1种。ReadDirectoryChangesW API
函数就是那样的一个例子,它只设有于依据 Windows NT
的操作系统中,并且只帮忙 Unicode;在那种气象下,您应该显式地接纳CharSet.Unicode。

奇迹,Windows API 是不是有字符集关系并不强烈。①种决不会有错的认同办法是在
Platform SDK 中反省该函数的 C
语言头文件。(假如你不可能自然要看哪个头文件,则足以查看 Platform SDK
文档中列出的各样 API 函数的头文件。)假如你发现该 API
函数确实定义为三个映射到以 A 或 W
结尾的函数名的宏,则字符集与你尝试调用的函数有提到。Windows API
函数的一个例证是在 WinUser.h 中声称的 GetMessage
API,您可能会惊奇地觉察它有 A 和 W 二种版本。

     贰、托管代码独立于阳台和语言,能更加好的落到实处分化语言平台中间的格外;

 

 StructLayout天性补助两种附加字段:CharSet、Pack、Size。    
·  
CharSet定义在协会中的字符串成员在布局被传给DLL时的排列格局。可以是Unicode、Ansi或Auto。    
  默认为Auto,在WIN
  NT/贰仟/XP中意味着字符串按照Unicode字符串进行排列,在WIN  
95/98/Me中则意味根据ANSI字符串进行排列。    
·  
Pack定义了协会的包装大小。能够是壹、二、四、8、1陆、3二、64、128或独特值0。特殊值0表示最近操作平台暗许的削减大小。    
 

3.3    SetLastError

SetLastError 错误处理十分首要,但在编制程序时平常被忘记。当您实行 P/Invoke
调用时,也会晤临其余的挑衅 — 处理托管代码中 Windows API
错误处理和相当之间的界别。笔者得以给你一点建议。

若是你正在利用 P/Invoke 调用 Windows API 函数,而对此该函数,您使用
GetLastError 来搜寻扩大的错误新闻,则应该在表面方法的 DllImportAttribute
中校 SetLastError 属性设置为 true。这适用于多数外部方法。

那会造成 CLSportage 在历次调用外部方法之后缓存由 API
函数设置的失实。然后,在卷入格局中,能够经过调用类库的
System.Runtime.InteropServices.马尔斯hal 类型中定义的
马尔斯hal.GetLastWin3二Error
方法来赢得缓存的荒唐值。小编的建议是反省那些愿意来自 API
函数的荒谬值,并为这个值引发三个可感知的可怜。对于别的具有波折景况(包罗根本就没意料到的曲折境况),则吸引在
System.ComponentModel 命名空间中定义的 Win3二Exception,并将
马尔斯hal.GetLastWin3二Error 再次来到的值传递给它。

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

不难易行的说,托管代码的话,.net可以自行释放资料,非托管代码需求手动释放资料.
  
对此非托管能源,您在应用程序中使用完那么些非托管财富之后,必须出示的假释他们,例如

  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct LIST_OPEN
    {
        public int dwServerId;
        public int dwListId;
        public System.UInt16 wRecordSize;
        public System.UInt16 wDummy;
        public int dwFileSize;
        public int dwTotalRecs;
        public NS_PREFETCHLIST sPrefetch;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
        public string szSrcMach;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
        public string szSrcComp;
    }

3.4    CallingConvention

CallingConvention.Cdecl : 调用方清理堆栈。它使你能够调用具有 varargs
的函数。

CallingConvention.StdCall :
被调用方清理堆栈。它是从托管代码调用非托管函数的暗中同意约定。

CallingConvention 字段的默许值为 Winapi,而后者又暗许为 StdCall 约定。

莫不是最不主要的二个 DllImportAttribute 属性是
CallingConvention。通过此属性,能够给 CL奥迪Q7提醒应该将哪类函数调用约定用于堆栈中的参数。CallingConvention.Winapi
的暗中认可值是最佳的精选,它在大部意况下都灵验。然则,假设该调用不起作用,则能够检查
Platform SDK 中的证明头文件,看看您调用的 API
函数是或不是是三个不合乎调用约定标准的老大 API。

普普通通,本机函数(例如 Windows API 函数或 C- 运维时 DLL
函数)的调用约定描述了何等将参数推入线程堆栈或从线程堆栈中排除。大部分Windows API
函数都是第二将函数的末尾三个参数推入堆栈,然后由被调用的函数负责清理该仓库。相反,许多
C-运营时 DLL
函数都被定义为遵守措施参数在措施签名中出现的逐一将其推入堆栈,将仓库清理工科作付出调用者。

碰巧的是,要让 P/Invoke
调用工作只须要让外围设备精通调用约定即可。平时,从私下认可值
CallingConvention.Winapi 开始是最佳的选料。然后,在 C 运维时 DLL
函数和个别函数中,大概必要将预订更改为 CallingConvention.Cdecl。

    
三、托管代码可分享CLGL450提供的劳务(如安全检查实验、垃圾回收等),不须求协调做到那些操作;

System.IO.StreamReader的3个文件对象,必须出示的调用对象的Close()方法关闭它,不然会占用系统

此例中用到MashalAs特性,它用于描述字段、方法或参数的封送处理格式。用它当作参数前缀并钦点目的须要的数据类型。
比如说,以下代码将两个参数作为数据类型长指针封送给 Windows API
函数的字符串 (LPStr):
[MarshalAs(UnmanagedType.LPStr)]
String existingfile;
[MarshalAs(UnmanagedType.LPStr)]
String newfile;

3.5    ExactSpelling

ExactSpelling 提示是还是不是应修改非托管 DLL 中的入口点的称谓,以与 CharSet
字段中钦赐的 CharSet 值相呼应。借使为 true,则当
DllImportAttribute.CharSet 字段设置为 CharSet 的 Ansi
值时,向方法名称中追加字母 A,当 DllImportAttribute.CharSet 字段设置为
CharSet 的 Unicode 值时,向方法的称号中扩充字母 W。此字段的暗中同意值是
false。

          非托管代码要求自个儿提供安全检查评定、垃圾回收等操作。

的内部存款和储蓄器和能源,而且或者会油可是生意外的错误。

[DllImport(“coredll.dll”)]
[return:
MarshalAs(UnmanagedType.Bool)]
public static extern bool
ReadMsgQueue(IntPtr hMsgQ, out POWER_BROADCAST BroadCast, uint
cbBufferSize, out uint lpNumberOfBytesRead, uint

3.6    PreserveSig

PreserveSig提醒托管方法签名不应转换来重返HRESULT、并且恐怕有三个一见青睐于再次来到值的附加 [out, retval]
参数的非托管签名。

.net的堆便是托管堆.没有非托管堆.引用类型的引用指标正是在堆里.

  清楚哪些是托管财富,什么是非托管能源

 

四      参数类型

l  数值型直接用相应的就可。(DWO哈弗D -> int , WOXC60D -> Int1六)

l  API中字符串指针类型 -> .net中string

l  API中句柄 (dWord) -> .net中IntPtr

l  API中组织 ->
.net中组织依旧类。注意那种状态下,要先用StructLayout天性限定声明结构或类

 

值类型的值就在栈里.

  最广泛的一类非托管能源便是包装操作系统资源的靶子,例如文件,窗口或互连网连接,对于那类财富

dw提姆eout, out uint
pdwFlags);注意组织作为参数时候,1般前边要丰硕ref修饰符,不然会出现谬误:对象的引用未有点名对象的实例。
[DllImport( “kernel32″, EntryPoint=”GetVersionEx” )]
public static extern bool GetVersionEx2( ref OSVersionInfo2 osvi );

五      Win3贰 API 中多少个常用的 DLL

DLL

内容说明

GDI32.dll

用于设备输出的图形设备接口 (GDI) 函数,例如用于绘图和字体管理的函数。

Kernel32.dll

用于内存管理和资源处理的低级别操作系统函数。

User32.dll

用于消息处理、计时器、菜单和通信的 Windows 管理函数。

所谓的体系资源.是指:网络连接,数据库连接.文件流.那种东西.

虽说垃圾回收器能够跟踪封装非托管能源的指标的生存期,但它不打听实际什么理清那些能源。幸亏.net

转自:

6      wince 中的DLL

DLL

内容说明

coredll.dll

 

那边的托管就是指被CL奥迪Q5管理,托管堆正是被CL冠道管理的堆。非托管能源必要手动释放,托管财富由GC帮你打理。

Framework提供了Finalize()方法,它同目的在于垃圾堆回收器回收该类能源时,适当的清理非托管资源。假诺

using能够跟踪非托管能源周期内的活动,一旦发现非托管能源生命甘休了,就会强制调用dispose方法去放活在该效用域的非托管能源的内部存款和储蓄器。

在MSDN Library
中搜索Finalize将会发觉许多好像的大旨,那里列举二种常见的非托管能源:

C#怎么直接调用非托管代码,经常有二种方法:

ApplicationContext,Brush,Component,ComponentDesigner,Container,Context,Cursor,FileStream,Fon

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

t,Icon,Image,Matrix,Object,OdbcDataReader,OleDBDataReader,Pen,Regex,Socket,StreamWriter,Time

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

r,Tooltip 等等财富。恐怕在利用的时候很多都并未有留意到!

从dll中导出函数:

至于托管能源,就不要说了撒,像简单的int,string,float,Date提姆e等等,.net中中国足球球组织一级联赛过十分之八的财富都以托

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

管资源。

b.将 DllImport 属性附加到该办法。DllImport 属性允许你钦赐包涵该格局的DLL 的名称。

非托管能源如何释放,.NET Framework 提供 Object.Finalize
方法,它同意对象在垃圾堆回收器回收该对

c.假若要求,为艺术的参数和再次来到值钦点自定义封送处理音信,那将重写 .NET
Framework 的暗许封送处理。

象使用的内部存款和储蓄器时适当清理其非托管能源。默许意况下,Finalize
方法不实行其它操作。暗中认可情况下,

using System;

using System.Runtime.InteropServices;

    public class MSSQL_ServerHandler

    {

        [DllImport("kernel32.dll")]

        public static extern int GetShortPathName

        (

            string path,

            StringBuilder shortPath,

            int shortPathLength

)

     }

Finalize
方法不实施别的操作。借使你要让垃圾回收器在回收对象的内部存款和储蓄器在此之前对指标执行清理操作,您

DllImportAttribute 的字段

总得在类中重写 Finalize
方法。但是大家都足以窥见在其实的编制程序中根本不或然override方法Finalize

 

(),在C#中,能够经过析构函数自动生成 Finalize 方法和对基类的 Finalize
方法的调用。

字段

说明

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"?"字符。

 

例如:
~MyClass()
{
  // Perform some cleanup operations here.
}
  该代码隐式翻译为下边包车型大巴代码。
protected override void Finalize()
{
  try
  {
    // Perform some cleanup operations here.
  }
  finally
  {
    base.Finalize();
  }
}

 

可是,在编制程序中,并不提出开始展览override方法Finalize(),因为,达成 Finalize
方法或析构函数对品质

 

大概会有负面影响。多少个简便的理由如下:用 Finalize
方法回收对象使用的内部存款和储蓄器要求至少五次垃圾回收

StructLayoutAttribute类

,当垃圾回收器回收时,它只回收未有终结器(Finalize方法)的不行访问的内存,那时她无法回收具有终

在C/C++中,struct类型中的成员的要是注解,则实例中成员在内部存款和储蓄器中的布局(Layout)顺序就定下来了,即与成员声称的逐一相同,并且在默许意况下再三再四根据组织中占据空间最大的分子开展对齐(Align);当然大家也足以透过安装或编码来设置内存对齐的形式.在.net托管环境中,CLHaval提供了更随意的办法来决定struct中Layout:我们得以在概念struct时,在struct上利用StructLayoutAttribute性子来支配成员的内部存款和储蓄器布局

结器(Finalize方法)的不得以访问的内部存款和储蓄器。它改为将那个目的的项从终止队列中移除并将她们放置在标记

 

为“准备停止”的目的列表中,该列表中的项针对托管堆中准备被调用其停下代码的对象,下次垃圾回收

C#提供了一个StructLayoutAttribute类,通过它你可以定义本人的格式化类型,在受管辖代码中,格式化类型是三个用StructLayoutAttribute表达的构造或类成员,通过它亦可确定保障其内部成员预期的布局音讯。布局的抉择共有二种:

器举办回收时,就回收并释放了这个内部存款和储蓄器。
C#咋样直接调用非托管代码,日常有2种办法:

布局选项  
描述  
LayoutKind.Automatic  
为了提升成效允许运维态对品种成员再次排序。  
小心:永远不要选拔这些选项来调用不受管辖的动态链接库函数。  
LayoutKind.Explicit  
对各类域依据FieldOffset属性对项目成员排序  
LayoutKind.Sequential  
对出现在受管辖类型定义地方的不受管辖内存中的品种成员举办排序。

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

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

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

 

本人首要商讨从dll中程导弹出函数,基本步骤如下:

 

1.使用
C# 关键字
static

extern
表明方法。

COM interop具体操作:

2.将
DllImport 属性附加到该办法。DllImport 属性允许你钦命包括该格局的 DLL
的称呼。

a. 用atl写com服务程序

叁.借使须求,为艺术的参数和再次来到值钦点自定义封送处理音讯,那将重写 .NET Framework
的暗中认可封送处理。

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

好,大家开头

   用如下命令:

1.第2我们查询MSDN找到GetShortPathName的概念

   tlbimp 你写的com.dll

The
GetShortPathName function retrieves the short path form of the
specified path.

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

DWORD
GetShortPathName(

c. 托管客户端相当简单

  LPCTSTR lpszLongPath**,**

   直接new一下,然后调用对应的不二法门即可。

  LPTSTR lpszShortPath**,**

 

  DWORD cchBuffer

 

);

 

二.查找对照表进行数据类型的转移(出处:  )Data
Types

 

 

 

Win32
Types

Specification

CLR
Type

char,
INT8, SBYTE, CHAR†

8-bit
signed integer

System.SByte

short,
short int, INT16, SHORT

16-bit
signed integer

System.Int16

int,
long, long int, INT32, LONG32, BOOL†, INT

32-bit
signed integer

System.Int32

__int64,
INT64, LONGLONG

64-bit
signed integer

System.Int64

unsigned
char, UINT8, UCHAR†, BYTE

8-bit
unsigned integer

System.Byte

unsigned
short, UINT16, USHORT, WORD, ATOM, WCHAR†, __wchar_t

16-bit
unsigned integer

System.UInt16

unsigned,
unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT

32-bit
unsigned integer

System.UInt32

unsigned
__int64, UINT64, DWORDLONG, ULONGLONG

64-bit
unsigned integer

System.UInt64

float,
FLOAT

Single-precision
floating point

System.Single

double, long
double, DOUBLE

Double-precision
floating point

System.Double

†In
Win32 this type is an integer with a specially assigned meaning; in
contrast, the CLR provides a specific type devoted to this
meaning.

 

三.调用GetShortPathName这几个API,不难的写法如下(编写翻译通过的话),

using
System;

using
System.Runtime.InteropServices;

    public class
MSSQL_ServerHandler

    {

        [DllImport(“kernel32.dll”)]

        public static
extern
int
GetShortPathName

        (

            string path,

            StringBuilder shortPath,

            int shortPathLength

)

     }

而大家事先的事例:

using
System;

using
System.Runtime.InteropServices;

    public class
MSSQL_ServerHandler

    {

        [DllImport(“kernel32.dll”, CharSet = CharSet.Auto)]

        public static extern int
GetShortPathName

        (

            [MarshalAs(UnmanagedType.LPTStr)] string path,

            [MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath,

            int shortPathLength

)

     }

相比较能够,当中DllImport
,static,extern基本上是必须有的,其余CharSet,马尔斯halAs(…)是可选择,在那边正是未有,程序也是能够调用此API了。

说明:

1.MSSQL_ServerHandler.
GetShortPathName
方法用
static

extern
修饰符评释同时拥有
DllImport
属性,该属性使用私下认可名称GetShortPathName
布告编写翻译器此完毕来源kernel32.dll。若要对
C# 方法运用区别的称号(如
getShort),则必须在
DllImport
属性中动用
EntryPoint
选项,如下所示:

[DllImport(“kernel32.dll”,
EntryPoint=”getShort”)]

2.利用马尔斯halAs(UnmanagedType.LPTStr)保障了在此外平台上都会博得LPTStr,不然私下认可的措施会把从C#中的字符串作为BStr传递。

 

近日只假诺仅包含简单参数和重临值的WIN32API,就都能够利用这种办法进行比较,简单的改写和调用了。

 

二.骨子里的规律**
―― 知其所以然,相关的文化**

 1.平台调用详原理

平台调用重视于元数据在运营时寻找导出的函数并封送其参数。下图显示了这一进程。

对非托管
DLL 函数的“平台调用”调用

金沙注册送58 1
当“平台调用”调用非托管函数时,它将依次执行以下操作:

追寻包蕴该函数的
DLL。

将该
DLL 加载到内部存款和储蓄器中。

检索函数在内存中的地址并将其参数推到堆栈上,以封送所需的数目。

注意   只在首先次调用函数时,才会寻找和加载
DLL 并招来函数在内存中的地址。

将控制权转移给非托管函数。

阳台调用会向托管调用方引发由非托管函数生成的那多少个。

 2**.关于Attribute(属性,注意青黄字)**

性子能够放置在大约拥有宣称中(但一定的习性大概限制它在其上有效性的注脚类型)。在语法上,属性的钦赐方法为:将括在方括号中的属性名置于其适用的实业注明在此之前。例如,具有
DllImport 属性的类将宣示如下:

[DllImport] public
class MyDllimportClass { … }

关于更多音信,请参见 DllImportAttribute 类。

许多质量都带参数,而那个参数能够是定位(未命名)参数也能够是命名参数。任何定点参数都无法不按一定顺序点名并且无法不难,而命名参数是可选的且能够按专擅顺序点名。首先钦命定位参数。例如,那三个脾气是一律的:

[DllImport(“user32.dll”,
SetLastError=false, ExactSpelling=false)]

[DllImport(“user32.dll”,
ExactSpelling=false, SetLastError=false)]

[DllImport(“user32.dll”)]

率先个参数(DLL 名称)是永恒参数并且三番五次第1个冒出,别的参数为命名参数。在此例中,多少个命名参数都暗中同意为假,由此它们可以归纳(有关默许参数值的新闻,请参见种种属性的文书档案)。

在3个声称中得以放置四个属性,可分别放置,也可放在同样组括号中:

bool
AMethod([In][Out]ref double x);

bool
AMethod([Out][In]ref double x);

bool
AMethod([In,Out]ref double x);

1些品质对于给定实体能够钦点数十次。此类可反复选取的性情的二个示范是 Conditional:

[Conditional(“DEBUG”),
Conditional(“TEST1”)] void TraceMethod() {…}

注意   基于约定,全数属性名称都是单词“Attribute”甘休,以便将它们与 .NET
Framework 中的其余项界别。可是,在代码中运用性质时不必要钦命属性后缀。例如,[DllImport] 虽等效于
[DllImportAttribute],但
DllImportAttribute 才是该属性在 .NET
Framework 中的实际名称。

3.MarshalAsAttribute

指令怎么着在托管代码和非托管代码之间封送数据。可将该属性应用于参数、字段或重临值。

该属性为可选属性,因为各样数据类型都有暗中认可的封送处理作为。

绝大多数意况下,该属性只是利用 UnmanagedType
枚举标识非托管数据的格式。

譬如说,暗中同意境况下,公共语言运行库将字符串参数作为
BStr 封送到 COM 方法,不过足以因而制定马尔斯halAs属性,
将字符串作为 LPStr、LPWStr、LPTStr
或 BStr
封送到非托管代码。某个
UnmanagedType 枚举成员要求增大音讯。

 

3:进阶,怎样处理含有复杂的参数和再次回到值类型的API的调用(To Be
Continue…)
Api函数是建筑Windws应用程序的基本,每壹种Windows应用程序开发工具,它提供的最底层函数都直接或直接地调用了Windows
API函数,同时为了贯彻效益扩展,一般也都提供了调用WindowsAPI函数的接口,
也正是说具备调用动态连接库的力量。Visual
C#和任何开发工具一样也能够调用动态链接库的API函数。.NET框架本人提供了那般壹种服务,允许受管辖的代码调用动态链接库中落到实处的非受管辖函数,包括操作系统提供的Windows
API函数。它能够稳定和调用输出函数,遵照必要,协会其各样参数(整型、字符串类型、数组、和布局等等)跨越互操作边界。

下面以C#为例简单介绍调用API的基本进度:  
动态链接库函数的注明  
 
动态链接库函数使用前必须注明,相对于VB,C#函数声明显示越来越罗嗦,前者通过
Api
Viewer粘贴未来,能够一向运用,而后者则要求对参数作些额外的转移工作。

 
动态链接库函数注脚部分壹般由下列两局地构成,一是函数名或索引号,2是动态链接库的公文名。  
 
譬如,你想调用User32.DLL中的MessageBox函数,我们必须指明函数的名字MessageBoxA或MessageBoxW,以及库名字User3二.dll,我们通晓Win3二API对各样关乎字符串和字符的函数一般都留存多个本子,单字节字符的ANSI版本和双字节字符的UNICODE版本。

  上边是二个调用API函数的事例:  
[DllImport(“KERNEL32.DLL”, EntryPoint=”MoveFileW”,
SetLastError=true,  
CharSet=CharSet.Unicode, ExactSpelling=true,  
CallingConvention=CallingConvention.StdCall)]  
public static extern bool MoveFile(String src, String dst);  

 
当中入口点EntryPoint标识函数在动态链接库的入口地点,在3个受管辖的工程中,目的函数的原知名字和序号入口点不仅标识1个跨越互操作界限的函数。而且,你还是能够把那么些入口点映射为贰个例外的名字,也正是对函数进行重命名。重命名能够给调用函数带来各个便利,通过重命名,一方面大家不用为函数的大小写伤透脑筋,同时它也能够保障与已某个命名规则保持一致,允许带有区别参数类型的函数共存,更关键的是它简化了对ANSI和Unicode版本的调用。CharSet用于标识函数调用所使用的是Unicode或是ANSI版本,ExactSpelling=false将告诉编写翻译器,让编译器决定采纳Unicode可能是Ansi版本。其它的参数请参见MSDN在线扶助.

 
在C#中,你能够在EntryPoint域通过名字和序号声明一(Wissu)(Karicare)个动态链接库函数,如若在格局定义中运用的函数名与DLL入口点相同,你不须求在EntryPoint域展现注脚函数。不然,你不可能不选取下列属特性式提醒四个名字和序号。

[DllImport(“dllname”, EntryPoint=”Functionname”)]  
[DllImport(“dllname”, EntryPoint=”#123″)]  
值得注意的是,你必须在数字序号前加“#”  
下面是1个用MsgBox替换Message博克斯名字的例证:  
[C#]  
using System.Runtime.InteropServices;  

public class Win32 {  
[DllImport(“user32.dll”, EntryPoint=”MessageBox”)]  
public static extern int MsgBox(int hWnd, String text, String caption,
uint type);  
}  
广大受管辖的动态链接库函数期望你可见传递多少个扑朔迷离的参数类型给函数,譬如一个用户定义的布局类型成员要么受管辖代码定义的一个类成员,那时你不能够不提供额外的信息格式化那一个类型,以保全参数原有的布局和对齐。

C#提供了3个StructLayoutAttribute类,通过它你可以定义自个儿的格式化类型,在受管辖代码中,格式化类型是多少个用StructLayoutAttribute表明的构造或类成员,通过它可以保险其里面成员预期的布局消息。布局的选料共有两种:

布局选项  
描述  
LayoutKind.Automatic  
为了提升作用允许运转态对项目成员再一次排序。  
只顾:永远不要采纳这些选项来调用不受管辖的动态链接库函数。  
LayoutKind.Explicit  
对种种域遵照FieldOffset属性对品种成员排序  
LayoutKind.Sequential  
对出现在受管辖类型定义地点的不受管辖内部存储器中的项目成员实行排序。  
传递结构成员  
上边包车型地铁例子表明怎么着在受管辖代码中定义三个点和矩形类型,并作为一个参数传递给User3二.dll库中的PtInRect函数,  
函数的不受管辖原型声明如下:  
BOOL PtInRect(const RECT *lprc, POINT pt);  
在意你必须透过引用传递Rect结构参数,因为函数须求叁个Rect的结构指针。  
[C#]  
using System.Runtime.InteropServices;  

[StructLayout(LayoutKind.Sequential)]  
public struct Point {  
public int x;  
public int y;  
}  

[StructLayout(LayoutKind.Explicit]  
public struct Rect {  
[FieldOffset(0)] public int left;  
[FieldOffset(4)] public int top;  
[FieldOffset(8)] public int right;  
[FieldOffset(12)] public int bottom;  
}  

class Win32API {  
[DllImport(“User32.dll”)]  
public static extern Bool PtInRect(ref Rect r, Point p);  
}  
接近你能够调用GetSystemInfo函数得到系统新闻:  
? using System.Runtime.InteropServices;  
[StructLayout(LayoutKind.Sequential)]  
public struct SYSTEM_INFO {  
public uint dwOemId;  
public uint dwPageSize;  
public uint lpMinimumApplicationAddress;  
public uint lpMaximumApplicationAddress;  
public uint dwActiveProcessorMask;  
public uint dwNumberOfProcessors;  
public uint dwProcessorType;  
public uint dwAllocationGranularity;  
public uint dwProcessorLevel;  
public uint dwProcessorRevision;  
}  
[DllImport(“kernel32”)]  
static extern void GetSystemInfo(ref SYSTEM_INFO pSI);  

SYSTEM_INFO pSI = new SYSTEM_INFO();  
GetSystemInfo(ref pSI);  

类成员的传递  
一如既往要是类具有2个恒定的类成员布局,你也得以传递三个类成员给二个不受管辖的动态链接库函数,上面包车型的士事例重要表达如何传递八个sequential顺序定义的MySystem提姆e类给User32.dll的GetSystemTime函数,
函数用C/C++调用标准如下:

void GetSystemTime(SYSTEMTIME* SystemTime);  
不像传值类型,类总是通过引用传递参数.  
[C#]  
[StructLayout(LayoutKind.Sequential)]  
public class MySystemTime {  
public ushort wYear;  
public ushort wMonth;  
public ushort wDayOfWeek;  
public ushort wDay;  
public ushort wHour;  
public ushort wMinute;  
public ushort wSecond;  
public ushort wMilliseconds;  
}  
class Win32API {  
[DllImport(“User32.dll”)]  
public static extern void GetSystemTime(MySystemTime st);  
}  
回调函数的传递:  
从受管辖的代码中调用超过一半动态链接库函数,你只需创造贰个受管辖的函数定义,然后调用它即可,那些进程丰裕直白。  
只要1个动态链接库函数须求多少个函数指针作为参数,你还索要做以下几步:  
先是,你不能够不参照有关这几个函数的文书档案,分明这一个函数是还是不是供给1个回调;第3,你不能不在受管辖代码中开创多少个回调函数;最终,你能够把指向那么些函数的指针作为3个参数创递给DLL函数,.

回调函数及其实现:  
回调函数平时用在职分急需再行执行的场面,譬如用于枚举函数,譬如Win3二 API
中的EnumFontFamilies(字体枚举), EnumPrinters(打字与印刷机), EnumWindows
(窗口枚举)函数. 下边以窗口枚举为例,谈谈怎么样通过调用EnumWindow
函数遍历系统中设有的具有窗口

分下边多少个步骤:  

  1. 在完成调用前先参考函数的注明  
    BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARMAM IParam)  
    眼看这些函数须求3个回调函数地址作为参数.  
    二.
    创建三个受管辖的回调函数,那么些事例声明为表示类型(delegate),也等于大家所说的回调,它蕴涵八个参数hwnd和lparam,首个参数是八个窗口句柄,第二个参数由应用程序定义,八个参数均为整形。

  
当那么些回调函数再次来到三个非零值时,标示执行成功,零则暗示战败,那个事例总是回到True值,以便不断枚举。  

  1. 终极创造以象征对象(delegate),并把它看作三个参数字传送递给EnumWindows
    函数,平台会自行地 把象征转化成函数能够分辨的回调格式。

[C#]  
using System;  
using System.Runtime.InteropServices;  

public delegate bool CallBack(int hwnd, int lParam);  

public class EnumReportApp {  

[DllImport(“user32”)]  
public static extern int EnumWindows(CallBack x, int y);  

public static void Main()  
{  
CallBack myCallBack = new CallBack(EnumReportApp.Report);  
EnumWindows(myCallBack, 0);  
}  

public static bool Report(int hwnd, int lParam) {  
Console.Write(“窗口句柄为”);  
Console.WriteLine(hwnd);  
return true;  
}  
}  
指针类型参数字传送递:  
  在Windows
API函数调用时,超越5/10函数接纳斯达克综合指数针传递参数,对3个布局变量指针,我们除了运用方面包车型客车类和协会格局传递参数之外,大家有时候还足以应用数组传递参数。

  上面这些函数通过调用GetUserName获得用户名  
BOOL GetUserName(  
LPTST奥德赛 lpBuffer, // 用户名缓冲区  
LPDWOCR-VD nSize // 存放缓冲区大小的地址指针  
);  
    
[DllImport(“Advapi32.dll”,  
EntryPoint=”GetComputerName”,  
ExactSpelling=false,  
SetLastError=true)]  
static extern bool GetComputerName (  
[MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer,  
  [MarshalAs(UnmanagedType.LPArray)] Int32[] nSize );  
  那一个函数接受五个参数,char * 和int
*,因为您不可能不分配2个字符串缓冲区以接受字符串指针,
您能够运用String类代替那一个参数类型,当然你还足以注解壹(Wissu)个字节数组传递ANSI字符串,同样你也足以声澳优(Ausnutria Hyproca)(Aptamil)个唯有二个成分的长整型数组,使用数组名作为第一个参数。上面的函数可以调用如下:

byte[] str=new byte[20];  
Int32[] len=new Int32[1];  
len[0]=20;  
GetComputerName (str,len);  
MessageBox.Show(System.Text.Encoding.ASCII.GetString(str));  
  最终索要提醒的是,每一种方法应用前必须在文书头加上:  
  using System.Runtime.InteropServices;

 

参考文章

1. 
Eric
Gunnerson的《使用
Win3二 和别的库》(非常好!!!)

2. 
MSDN:C# 程序员参考 平台调用教程

3.  《在
C# 中通过
P/Invoke 调用Win32
DLL》Jason
Clark

4.   Calling Win32 DLLs in C# with
P/Invoke

5. 
《暴强贴:从.NET平台调用Win32API》水之真谛

相关文章

网站地图xml地图