【美高梅开户网址】API或称非托管代码,托管代码的牵线

.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
中并未有//壹致的实例概念。接下来,还要注意该办法被标记为
extern。那是提示编译器该措施是通//过1个从 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时,运维库排列那一个成分的艺术。

【美高梅开户网址】API或称非托管代码,托管代码的牵线。二      托管代码 (managed code)

.NET
Framework的为主是其运维库的进行环境,称为公共语言运维库(CL奥迪Q7)或.NET运维库。平常将在CLCRUISER的控制下运作的代码称为托管代码(managed
code)。

运维库环境(而不是一直由操作系统)执行的代码。托管代码应用程序能够取得公共语言运转库服务,例如自动垃圾回收、运维库类型检查和安全帮衬等。那几个服务帮扶提供单身于阳台和语言的、统一的托管代码应用程序行为。

  托管代码是足以选用20各个匡助Microsoft .NET
Framework的尖端语言编写的代码,它们包含:C#, J#, Microsoft Visual
Basic .NET, Microsoft JScript .NET,
以及C++。全数的语言共享统1的类库集合,并能被编码成为中等语言(IL)。运行库编写翻译器(runtime-aware
ompiler)在托管执行环境下编写翻译中间语言(IL)使之变成本地可实施的代码,并利用数组边界和目录检查,卓殊处理,垃圾回收等伎俩保险项指标平安。

 

  在托管执行环境中利用托管代码及其编写翻译,能够制止过多一级的导致安全黑洞和不安定程序的编制程序错误。同样,许多不牢靠的统一筹划也自动的被升高了安全
性,例如类型安全检查,内部存款和储蓄器管理和假释无效对象。程序员可以花更加多的生机关心程序的应用逻辑设计并得以减掉代码的编写量。那就象征越来越短的支付时间和更健
壮的次序。

 

简言之点说,托管代码是microsoft的中等语言,他主要的效能是在.NET
FRAMEWO凯雷德K的CLCR-V执行代码前去编写翻译源代码,也正是说托管代码充当着翻译的功用,源代码在运作时刻为七个等级:

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

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

 

只是精通.net
CL福特Explorer怎么办那几个操作。也正是说对于你的应用程序创制的多数目的,能够凭借
.NET

 

二.壹     非托管代码 (unmanaged code)

  在集体语言运转库环境的表面,由操作系统直接执行的代码。非托管代码必须提供温馨的垃圾堆回收、类型检查、安全帮助等劳动;它与托管代码分化,后者从集体语言运营库中获取那么些服务。

.net中托管代码的意思

托管代码(Managed
Code)实际上正是个中语言(IL)代码。代码编写实现后开展编写翻译,此时编写翻译器把代码编写翻译成人中学间语言(IL),而不是能从来在你的电脑上运营的机器码。程序集(Assembly)的文书负责打包中间语言,程序集中包括了描述所创办的办法、类以及品质的具有元数据。
托管代码在公共语言运营库(CLEscort)中运作。CLCRUISER提供了3个实时编写翻译器,用来把IL代码编写翻译为本机机器代码.那样1来,CL途乐能够使代码变得可移植,因为.NET应用程序的源代码必须被编写翻译为IL代码,那个IL代码能够运转在另外提供CLR服务的平台上.从CL帕杰罗的角度来看,怀有的言语都以1致的,只要有3个能生成IL代码的编写翻译器就行,那就保障了种种语言的互操性.

Framework 的污源回收器隐式地实施全体需要的内部存款和储蓄器管理职务。托管代码正是基于.net元数据格式的代码,
运行于.net平台之上,全部的与操作系统的置换有.net来成功,就如把那几个效应委托给.net,所以称为托管代码。

 

二.2     什么是托管?托管是什么样意思?

托管代码正是基于.net元数据格式的代码,运转于.net平台之上,全部的与操作系统的置换有.net来成功,就如把这么些职能源委员会托给.net,所以称为托管代码。非托管代码则恰恰相反。

举个例子l

Vc.net还足以接纳mfc,atl来编写程序,他们依据MFC恐怕ATL,而不是.NET,所以是非托管代码,倘诺基于.net比如C#,VB.net则是托管代码

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

一句话来说的说,托管代码的话,.net能够自行释放资料,非托管代码须求手动释放资料.

什么是托管C++

托管是.NET的三个特意概念,它提倡1种新的编制程序理念,因而我们完全能够把“托管”视为“.NET”。由托管概念所掀起的C++应用程序包罗托管代码、托管数据和托管类多少个组成都部队分。

托管代码

.Net环境提供了不可胜道为主的运转(RUNTIME)服务,比如非常处理和安全策略。为了能应用这个服务,必须要给运营条件提供一些音信代码(元数
据),那种代码就是托管代码。全体的C#、VB.NET、JScript.NET默许时都是托管的,但Visual
C++默许时不是托管的,必须在编写翻译器中应用命令行选项(/CLHighlander)才能发出托管代码。

托管数据

与托管代码密切相关的是托管数据。托管数据是由公共语言运转的排放物回收器举办分红和假释的数码。暗中同意意况下,C#、Visual
Basic 和 JScript.NET 数据是托管数据。但是,通过行使越发的机要字,C#
数据能够被标记为非托管数据。Visual
C++数据在默许情状下是非托管数据,即使在利用 /CL哈弗 开关时也不是托管的。

托管类

固然Visual
C++数据在暗中认可境况下是非托管数据,可是在动用C++的托管扩充时,能够接纳“__gc”关键字将类标志为托管类。就如该名称所体现的那样,它代表类实
例的内部存储器由垃圾回收器管理。别的,三个托管类也统统能够成为 .NET
框架的成员,因此能够带来的便宜是,它可以与其余语言编写的类正确地展开互动操作,如托管的C++类能够从Visual
Basic类继承等。但与此同时也有1对限量,如托管类只好从二个基类继承等。

非托管代码

举个例证l 

能够透过System.Runtime.InteropServices.StructLayout  
特征精确的决定每2个构造成员的地方。
System.Runtime.InteropServices.StructLayout  
同意的值有StructLayout.Auto   StructLayout.Sequential  
StructLayout.Explicit.
    
一.Sequential,顺序布局,比如
struct
S1
{
  int a;
  int b;
}
这正是说暗中同意景况下在内存里是先排a,再排b
约等于壹旦能取到a的地址,和b的地点,则离开2个int类型的长短,四字节
[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中附带的品种库导入程序。用那些命令就是把生成2个非托管com
dll的托管包装。

c. 托管客户端格外不难

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

  1. P/Invoke

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

介绍贰个P/Invoke网址,

其一网址根本是一个wiki,允许开发者发现,编辑,增加PInvoke的签署,用户自定义类型和从托管代码(指c#和VB.net开发语言)访问win3贰和别的非托管api的新闻。

世界内地的.Net开发者能够很不难享受温馨有价值的事物给社区,

在公家语言运维库条件的表面,由操作系统直接执行的代码。非托管代码总得提供温馨的垃圾堆回收、类型检查、安全支持等服务,它与托管代码不一致,后者从国有语言运转库中收获这几个劳动,而非托管代码是在运营库之对外运输行的代码。例如COM
组件、ActiveX 接口和 Win3二 API
函数都以非托管代码的示例。

 

struct S1
{
  int a;
  int
b;
}
这么和上贰个是同样的.因为暗中同意的内部存款和储蓄器排列正是Sequential,也正是按成员的先后顺序排列.
二.Explicit,精确布局
内需用FieldOffset()设置每一种成员的职责
如此就足以兑现类似c的公用体的意义
[StructLayout(LayoutKind.Explicit)]

二.肆     托管代码和非托管代码效用的相比较

列席原作 来自

更详细的音讯

区别:

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 的显要作用是给 CLOdyssey 提醒哪个 DLL
导出你想要调用的函数。相关 DLL 的名目被看成叁个构造函数参数字传送递给
DllImportAttribute。

下表列出了有着与平台调用相关的表征字段。
对于各个字段,下表都将含有其暗中认可值,并且会提供三个链接,用于获取有关怎么着运用这么些字段定义非托管
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哈弗上;

 

 

3.1     entrypoint

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

以下列出了重命名 DLL 函数的或是原因:

·        制止采用分别轻重缓急写的 API 函数名

·        符合于今的命名标准

·        提供利用分裂数据类型的函数(通过注明同1 DLL 函数的多个版本)

·        简化对含蓄 ANSI 和 Unicode 版本的 API 的选用

 

您能够行使
DllImportAttribute.EntryPoint
字段按名称或序号钦点 DLL 函数。如果函数在章程定义中的名称与入口点在 DLL
的名称①致,则无需用 EntryPoint
字段来显式地方统一标准识函数。不然,使用以下属性形式之一来提示名称或序号:

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
中查找函数名的点子。本主旨将介绍这三种表现。

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

·        MessageBoxA

提供单字节字符 ANSI 格式,其性情是在入口点名称后附加二个“A”。对
MessageBoxA 的调用始终会以 ANSI 格式封送字符串,它宽广于 Windows 九伍和 Windows 玖捌 平台。

·        MessageBoxW

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

CharSet 字段接受以下值:

CharSet.Ansi(默认值)

·        字符串封送处理

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

·        名称相配


DllImportAttribute.ExactSpelling
字段为 true(它是 Visual Basic 200第55中学的暗许值)时,平台调用将只搜索您钦点的称谓。例如,假诺钦赐MessageBox,则平台调用将搜索
MessageBox,假使它找不到完全相同的拼写则战败。

ExactSpelling 字段为 false(它是 C++ 和 C#
中的默许值)时,平台调用将率先搜索未处理的别称(MessageBox),假使找不到未处理的外号,则将追寻已处理的名称
(MessageBoxA)。请小心,ANSI 名称相称行为与 Unicode
名称相称行为不相同。

CharSet.Unicode

·        字符串封送处理

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

·        名称相称

ExactSpelling 字段为 true(它是 Visual Basic 二〇〇七中的暗中认可值)时,平台调用将只搜索您内定的名称。例如,借使钦点MessageBox,则平台调用将搜索
MessageBox,就算它找不到完全相同的拼写则失利。

ExactSpelling 字段为 false(它是 C++ 和 C#
中的暗中同意值)时,平台调用将第3搜索已处理的名称
(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 98上为 Ansi)。即便 ExactSpelling 设置为 true,则只有当 DLL
中留存“MyMethod”时才回去“MyMethod”。

要是 DLL 函数不以任何方法处理公事,则足以忽略 DllImportAttribute 的
CharSet 属性。然则,当 Char 或 String 数据是等式的1局地时,应该将
CharSet 属性设置为 CharSet.Auto。那样能够使 CLSportage 依照宿主 OS
使用合适的字符集。假使未有显式地设置 CharSet 属性,则其暗中认可值为
CharSet.Ansi。这几个暗中同意值是有缺点的,因为对于在 Windows 两千、Windows XP
和 Windows NT® 上开始展览的 interop
调用,它会被动地影响文本参数封送处理的品质。

应当显式地采取 CharSet.Ansi 或 CharSet.Unicode 的 CharSet 值而不是运用
CharSet.Auto
的唯一景况是:您显式地钦点了多少个导出函数,而该函数特定于那二种 Win32 OS
中的某1种。ReadDirectoryChangesW API
函数便是这么的3个例子,它只存在于依据 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/2000/XP中象征字符串依照Unicode字符串进行排列,在WIN  
95/98/Me中则意味着依据ANSI字符串进行排列。    
·  
Pack定义了社团的包裹大小。能够是一、2、四、8、1陆、3二、6四、128或尤其值0。特殊值0表示如今操作平台暗中同意的收缩大小。    
 

3.3    SetLastError

SetLastError 错误处理相当主要,但在编制程序时平日被淡忘。当您实行 P/Invoke
调用时,也相会临其余的挑衅 — 处理托管代码中 Windows API
错误处理和充足之间的区分。作者能够给你一点提出。

假如您正在利用 P/Invoke 调用 Windows API 函数,而对于该函数,您使用
GetLastError 来寻找扩张的错误音讯,则应当在表面方法的 DllImportAttribute
中校 SetLastError 属性设置为 true。这适用于超越二分之一外部方法。

这会导致 CL大切诺基 在每一趟调用外部方法之后缓存由 API
函数设置的不当。然后,在包装措施中,能够透过调用类库的
System.Runtime.InteropServices.马尔斯hal 类型中定义的
马尔斯hal.GetLastWin3二Error
方法来获取缓存的荒谬值。作者的提出是检查那一个愿意来自 API
函数的一无所长值,并为那么些值引发二个可感知的卓殊。对于其余具备波折意况(包含根本就没意料到的破产情况),则迷惑在
System.ComponentModel 命名空间中定义的 Win32Exception,并将
马尔斯hal.GetLastWin32Error 再次回到的值传递给它。

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

简不难单的说,托管代码的话,.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。通过此属性,能够给 CLBMWX五提醒应该将哪一类函数调用约定用于堆栈中的参数。CallingConvention.Winapi
的私下认可值是最佳的选项,它在大多数景观下都灵验。然则,假若该调用不起效能,则能够检查
Platform SDK 中的申明头文件,看看您调用的 API
函数是还是不是是三个不适合调用约定标准的要命 API。

常备,本机函数(例如 Windows API 函数或 C- 运营时 DLL
函数)的调用约定描述了如何将参数推入线程堆栈或从线程堆栈中清除。半数以上Windows API
函数都以首先将函数的结尾2个参数推入堆栈,然后由被调用的函数负责清理该仓库。相反,许多
C-运转时 DLL
函数都被定义为依照办法参数在措施签名中出现的各样将其推入堆栈,将仓库清理工科作付出调用者。

碰巧的是,要让 P/Invoke
调用工作只供给让外围设备领会调用约定即可。日常,从默许值
CallingConvention.Winapi 开首是最棒的挑叁拣4。然后,在 C 运营时 DLL
函数和个别函数中,恐怕须要将预定更改为 CallingConvention.Cdecl。

    
3、托管代码可享受CL陆风X8提供的劳动(如安全检查实验、垃圾回收等),不必要团结姣好这个操作;

System.IO.StreamReader的三个文本对象,必须出示的调用对象的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  数值型直接用相应的就可。(DWOCR-VD -> int , WOOdysseyD -> Int1陆)

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

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

l  API中布局 ->
.net中结构依旧类。注意那种地方下,要先用StructLayout性子限定表明结构或类

 

值类型的值就在栈里.

  最常见的一类非托管财富正是包裹操作系统资源的指标,例如文件,窗口或网络连接,对于那类能源

dwTimeout, out uint
pdwFlags);注意组织作为参数时候,一般前边要足够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

 

此地的托管正是指被CLLX570管理,托管堆即是被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,DateTime等等,.net中中国足球球协会一级联赛过8/10的财富都以托

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
方法或析构函数对性能

 

兴许会有负面影响。1个归纳的说辞如下:用 Finalize
方法回收对象使用的内部存款和储蓄器供给至少三次垃圾回收

StructLayoutAttribute类

,当垃圾回收器回收时,它只回收没有终结器(Finalize方法)的不行访问的内部存款和储蓄器,那时他不可能回收具有终

在C/C++中,struct类型中的成员的比方注解,则实例中成员在内部存款和储蓄器中的布局(Layout)顺序就定下来了,即与成员声称的依次相同,并且在暗中同意意况下接二连三依照组织中据为己有空间最大的积极分子进行对齐(Align);当然大家也能够因此设置或编码来安装内部存款和储蓄器对齐的格局.在.net托管环境中,CL宝马7系提供了更自由的办法来控制struct中Layout:我们能够在概念struct时,在struct上应用StructLayoutAttribute天性来决定成员的内存布局

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

 

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

C#提供了二个StructLayoutAttribute类,通过它你能够定义本身的格式化类型,在受管辖代码中,格式化类型是贰个用StructLayoutAttribute表达的协会或类成员,通过它亦可确定保障在那之中间成员预期的布局新闻。布局的接纳共有三种:

器展开回收时,就回收并释放了那个内部存储器。
C#怎样直接调用非托管代码,平时有贰种情势:

布局选项  
描述  
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.首先大家询问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
布告编写翻译器此落成来源kernel3二.dll。若要对
C# 方法应用不一致的名称(如
getShort),则必须在
DllImport
属性中运用
EntryPoint
选项,如下所示:

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

2.应用马尔斯halAs(UnmanagedType.LPTStr)保险了在其余平台上都会获得LPTStr,不然暗许的不二诀要会把从C#中的字符串作为BStr传递。

 

方今假如是仅包蕴简单参数和重回值的WIN3二API,就都能够应用那种办法开始展览相比,容易的改写和调用了。

 

二.私下的规律**
―― 知其所以然,相关的学识**

 1.平台调用详原理

阳台调用正视于元数据在运转时追寻导出的函数并封送其参数。下图显示了那壹进程。

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

美高梅开户网址 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个冒出,别的参数为命名参数。在此例中,五个命名参数都暗中同意为假,由此它们能够大致(有关暗中同意参数值的音信,请参见各样属性的文书档案)。

在二个宣称中得以放置陆特性格,可分别放置,也可放在同样组括号中:

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

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

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

一点质量对于给定实体能够钦赐多次。此类可反复利用的品质的二个演示是 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 枚举成员须求增大音讯。

 

三:进阶,如何处理含有复杂的参数和再次来到值类型的API的调用(To Be
孔蒂nue…)
Api函数是修建Windws应用程序的基础,每壹种Windows应用程序开发工具,它提供的平底函数都直接或直接地调用了Windows
API函数,同时为了促功能益扩张,一般也都提供了调用WindowsAPI函数的接口,
也正是说具备调用动态连接库的能力。Visual
C#和其他开发工具一样也能够调用动态链接库的API函数。.NET框架自己提供了这么1种服务,允许受管辖的代码调用动态链接库中贯彻的非受管辖函数,包涵操作系统提供的Windows
API函数。它亦可稳定和调用输出函数,根据须要,组织其各类参数(整型、字符串类型、数组、和组织等等)跨越互操作边界。

下面以C#为例简单介绍调用API的宗旨过程:  
动态链接库函数的注明  
 
动态链接库函数使用前必须注脚,相对于VB,C#函数声分明示尤为罗嗦,前者通过
Api
Viewer粘贴今后,能够一贯运用,而后者则须要对参数作些额外的变化学工业作。

 
动态链接库函数表明部分一般由下列两有个别构成,一是函数名或索引号,二是动态链接库的文书名。  
 
譬如,你想调用User3二.DLL中的MessageBox函数,我们无法不指明函数的名字MessageBoxA或MessageBoxW,以及库名字User32.dll,我们清楚Win32API对每1个事关字符串和字符的函数一般都设有五个本子,单字节字符的ANSI版本和双字节字符的UNICODE版本。

  上面是2个调用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个受管辖的工程中,指标函数的本来名字和序号入口点不仅标识3个跨越互操作界限的函数。而且,你还是可以够把那些入口点映射为三个不一的名字,也正是对函数进行重命名。重命名能够给调用函数带来各类方便,通过重命名,1方面大家绝不为函数的分寸写伤透脑筋,同时它也得以确定保障与已有些命名规则保持1致,允许带有分歧参数类型的函数共存,更主要的是它简化了对ANSI和Unicode版本的调用。CharSet用于标识函数调用所运用的是Unicode或是ANSI版本,ExactSpelling=false将报告编写翻译器,让编写翻译器决定选用Unicode可能是Ansi版本。其余的参数请参见MSDN在线支持.

 
在C#中,你能够在EntryPoint域通过名字和序号声惠氏(WYETH)个动态链接库函数,若是在艺术定义中动用的函数名与DLL入口点相同,你不供给在EntryPoint域显示评释函数。否则,你必须使用下列属性子式提醒贰个名字和序号。

[DllImport(“dllname”, EntryPoint=”Functionname”)]  
[DllImport(“dllname”, EntryPoint=”#123″)]  
值得注意的是,你必须在数字序号前加“#”  
下边是3个用MsgBox替换MessageBox名字的例证:  
[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);  
}  
不少受管辖的动态链接库函数期望你能够传递二个错综复杂的参数类型给函数,譬如一个用户定义的协会类型成员要么受管辖代码定义的2个类成员,那时你不能够不提供额外的音信格式化那么些项目,以保持参数原有的布局和对齐。

C#提供了二个StructLayoutAttribute类,通过它你能够定义自个儿的格式化类型,在受管辖代码中,格式化类型是八个用StructLayoutAttribute表达的结构或类成员,通过它亦可确认保障其内部成员预期的布局消息。布局的挑三拣4共有三种:

布局选项  
描述  
LayoutKind.Automatic  
为了提升效用允许运维态对品种成员再一次排序。  
在意:永远不要接纳那一个选项来调用不受管辖的动态链接库函数。  
LayoutKind.Explicit  
对各样域根据菲尔德Offset属性对项目成员排序  
LayoutKind.Sequential  
对出现在受管辖类型定义位置的不受管辖内部存款和储蓄器中的类型成员开始展览排序。  
传送结构成员  
下边的例证表达什么在受管辖代码中定义三个点和矩形类型,并作为贰个参数字传送递给User32.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);  

类成员的传递  
1样借使类具有二个稳住的类成员布局,你也能够传递一个类成员给一个不受管辖的动态链接库函数,下边包车型大巴例子主要表明怎样传递2个sequential顺序定义的MySystemTime类给User3二.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);  
}  
回调函数的传递:  
从受管辖的代码中调用大部分动态链接库函数,你只需成立二个受管辖的函数定义,然后调用它即可,那几个历程足够直白。  
一旦3个动态链接库函数必要七个函数指针作为参数,你还须求做以下几步:  
先是,你不可能不参照有关这一个函数的文书档案,鲜明那些函数是或不是须要一个回调;第二,你不能够不在受管辖代码中开创三个回调函数;最终,你可以把指向那么些函数的指针作为3个参数创递给DLL函数,.

回调函数及其完毕:  
回调函数平日用在职责急需重新执行的场馆,譬如用于枚举函数,譬如Win3二 API
中的EnumFontFamilies(字体枚举), EnumPrinters(打字与印刷机), EnumWindows
(窗口枚举)函数. 上边以窗口枚举为例,谈谈怎样通过调用EnumWindow
函数遍历系统中设有的兼具窗口

分下边多少个步骤:  

  1. 在实现调用前先参考函数的扬言  
    BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARMAM IParam)  
    芸芸众生那一个函数需求三个回调函数地址作为参数.  
    二.
    成立三个受管辖的回调函数,这些事例注脚为表示类型(delegate),也正是我们所说的回调,它包含四个参数hwnd和lparam,第三个参数是二个窗口句柄,第贰个参数由应用程序定义,五个参数均为整形。

  
当那个回调函数重返1个非零值时,标示执行成功,零则暗示退步,那个事例总是回到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函数调用时,超过二分一函数选择指针传递参数,对2个布局变量指针,我们除了使用方面包车型地铁类和协会情势传递参数之外,大家有时还是能动用数组传递参数。

  上边这么些函数通过调用GetUserName获得用户名  
BOOL GetUserName(  
LPTST昂Cora lpBuffer, // 用户名缓冲区  
LPDWO瑞鹰D 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
*,因为你不能够不分配二个字符串缓冲区以接受字符串指针,
你能够使用String类代替这些参数类型,当然你还足以声宾博个字节数组传递ANSI字符串,同样你也得以声雅培(Abbott)个唯有三个元素的长整型数组,使用数组名作为第3个参数。上边包车型大巴函数能够调用如下:

byte[] str=new byte[20];  
Int32[] len=new Int32[1];  
len[0]=20;  
GetComputerName (str,len);  
MessageBox.Show(System.Text.Encoding.ASCII.GetString(str));  
  最终索要提示的是,每1种方法运用前务必在文书头加上:  
  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平台调用Win3二API》水之真谛

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图