.Net Framework
虽说已经实现了相当完善的功能,但在有些地方,由于一些特别的需求,卡发人员还是会被迫要调用
Windows API
,这是,我们就不得不要求应用
Managed Code
去调用
Unmanaged Code
。这也是本文要和大家所分享的
P/Invoke
。当然,其实
dotNet Framework
本身就是
P/Invoke
的最大用户。
:)
首先,要应用
P/Invoke
技术,要引入以下名字空间,以及以下两个特性
(Attribute.)
using
System.Runtime.InteropServices;
DllImportAttribute
MarshalAsAttribute
DllImportAttribute
MarshalAsAttribute
在应用
P/Invoke
时,最关键的一点便是参数对齐,我会在以下的讨论中强调这一点。现在让我们来看一个简单的例子,然机箱喇叭发出“嘟”的一声。
(
为了方便,我先贴出所有代码再做进一步的解释
)
using System;
using System.Runtime.InteropServices;
namespace PInvoke
{
class WinAPI
{
#region Extern Element
//BOOL Beep(
// DWORD dwFreq,
// DWORD dwDuration
//);
[DllImport("Kernel32.dll", EntryPoint = "Beep")]
static extern Boolean Beep(Int32 freq, Int32 duration);
#endregion
static public void TestFunction() {
Beep(750, 300);
}
}
}
在这里,我使用之前提到的 DllImportAttribute 从非托管的 Dll , Kernel32.dll 中引入函数 Beep ,然后再在托管代码中调用它。在这里,我直接给出了该 Dll 的名字 Kernel32 .dll 而并没有给出其绝对路径,这是因为该 Dll 位于 %SystemRoot%/system32 文件夹下。否则,一般要求给出 Dll 的绝对或相对路径。
另外就是这里给出的
C#
中
Beep
函数的签名,通过查看
Windows SDK
,我们知道,
Beep
函数接受两个
DWORD
的参数,再通过查阅
MSDN
得知
DWORD
表示的是无符号的
32
位整数。还记得我之前提到的参数对齐吗?那么在
P/Invoke
调用时也给出两个
32
位整数作为其参数,在这里我使用的是
Int32
。
最后,还要提醒的是,在
C#
中定义这类非托管函数的签名,要使用
extern
关键字。
相关文章: