.net 架構程式可以通過靜態 DLL 進入點的方式來訪問機器碼庫。DllImport 屬性用於指定包含外部方法的實現的dll 位置。
DllImport 屬性定義如下:
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Method)]
public class DllImportAttribute: System.Attribute
{
public DllImportAttribute(string dllName) {...}
public CallingConvention CallingConvention;
public CharSet CharSet;
public string EntryPoint;
public bool ExactSpelling;
public bool PreserveSig;
public bool SetLastError;
public string Value { get {...} }
}
}
說明:
1、DllImport只能放置在方法聲明上。
2、DllImport具有單個定位參數:指定包含被匯入方法的 dll 名稱的 dllName 參數。
3、DllImport具有五個具名引數:
a、CallingConvention 參數指示進入點的呼叫慣例。如果未指定 CallingConvention,則使用預設值 CallingConvention.Winapi。
b、CharSet 參數指示用在進入點中的字元集。如果未指定 CharSet,則使用預設值 CharSet.Auto。
c、EntryPoint 參數給出 dll 中進入點的名稱。如果未指定 EntryPoint,則使用方法本身的名稱。
d、ExactSpelling 參數指示 EntryPoint 是否必須與指示的進入點的拼字完全符合。如果未指定 ExactSpelling,則使用預設值 false。
e、PreserveSig 參數指示方法的簽名應當被保留還是被轉換。當簽名被轉換時,它被轉換為一個具有 HRESULT 傳回值和該傳回值的一個名為 retval 的附加輸出參數的簽名。如果未指定 PreserveSig,則使用預設值 true。
f、SetLastError 參數指示方法是否保留 Win32"上一錯誤"。如果未指定 SetLastError,則使用預設值 false。
4、它是一次性屬性類。
5、此外,用 DllImport 屬性修飾的方法必須具有 extern 修飾符。
下面是 C# 調用 Win32 MessageBox 函數的樣本:
using System;
using System.Runtime.InteropServices;
class MainApp
{
//通過DllImport引用user32.dll類。MessageBox來自於user32.dll類
[DllImport("user32.dll", EntryPoint="MessageBox")]
public static extern int MessageBox(int hWnd, String strMessage, String strCaption, uint uiType);
public static void Main()
{
MessageBox( 0, "您好,這是 PInvoke!", ".net", 0 );
}
}
物件導向的程式設計語言幾乎都用到了抽象類別這一概念,抽象類別為實現抽象事物提供了更大的靈活性。C#也不例外, C#通過覆蓋虛介面的技術深化了抽象類別的應用。欲瞭解這方面的知識,請看下一節-覆蓋虛介面
這裡講述的是C#調用標準動態庫的問題, 在我以前的檔案中講到過, C#調用Win32API, 原理是一樣的. 這裡我詳細講解用C寫一個標準的動態庫, 然後讓C#調用. (本篇適合初學者, 中間沒有任何冗餘代碼, 簡潔明了)
軟體環境: VC6.0(當然其他版本的VC5也可以)
1.製作標準動態庫
__declspec(dllexport) int __cdecl add(int, int);//這一句是聲明動態庫輸出一個可供外不調用的函數原型.
int add(int a,int b) {//實現這個函數
return a+b;
}
以上簡單3行代碼,聲明一個add的方法, 輸入參數是兩個int參數,返回這兩個數之和. 儲存為MyLib.c
然後執行編譯命令.
H:\XSchool\C#-School\HowTo>cl /LD MyLib.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
Copyright (C) Microsoft Corp 1984-1998. All rights reserved.
MyLib.c
Microsoft (R) Incremental Linker Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
/out:MyLib.dll
/dll
/implib:MyLib.lib
MyLib.obj
Creating library MyLib.lib and object MyLib.exp
確信有以上輸出, 說明編譯成功產生了動態庫.
2.編寫C-Sharp程式調用該動態庫
using System;
using System.Runtime.InteropServices;//這是用到DllImport時候要引入的包
public class InvokeDll {
[DllImport("MyLib.dll", CharSet=CharSet.Auto)]
static extern int add(int a,int b);//聲明外部的標準動態庫, 跟Win32API是一樣的.
public static void Main() {
Console.WriteLine(add(10,30));
}
}
儲存為InvokeDll.cs檔案, 與MyLib.dll置於同一目錄, 編譯該檔案.
H:\XSchool\C#-School\HowTo>csc invokedll.cs
將產生Invokedll.exe, 可以執行該檔案.
以上是C-Sharp調用標準動態庫的全過程, 本來覺得很簡單的東西, 一直都沒有想寫, 碰巧今日遇一朋友問及此事, 就順便寫了下來.