程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> DllImport attribute的總結,dllimportattribute

DllImport attribute的總結,dllimportattribute

編輯:C#入門知識

DllImport attribute的總結,dllimportattribute


C#有沒有方法可以直接都用已經存在的功能(比如Windows中的一些功能,C++中已經編寫好的一些方法),而不需要重新編寫代碼?

答案是肯定,就是通過接下來要說的 DllImport 。

     DllImport的namespace: using System.Runtime.InteropServices;

    MSDN中對DllImportAttribute的解釋:可將該屬性應用於方法。

    DllImportAttribute 屬性提供對從非托管 DLL 導出的函數進行調用所必需的信息。必須提供包含入口點的 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 修飾符。

   
DllImport的用法:

  DllImport("MyDllImport.dll")]
   private static extern int mySum(int a,int b);


一 在C#程序設計中使用Win32類庫
 常用對應類型:
1、DWORD 是 4 字節的整數,因此我們可以使用 int 或 uint 作為 C# 對應類型。
2、bool 類型與 BOOL 對應。

示例一:調用 Beep() API 來發出聲音
    Beep() 是在 kernel32.lib 中定義的,在MSDN 中的定義,Beep具有以下原型:

BOOL Beep(DWORD dwFreq, // 聲音頻率 
            DWORD dwDuration // 聲音持續時間); 

用 C# 編寫以下原型:

[DllImport("kernel32.dll")] 
public static extern bool Beep(int frequency, int duration);


示例二:枚舉類型和常量
  
  MessageBeep() 是在 user32.lib 中定義的,在MSDN 中的定義,MessageBeep具有以下原型:

 BOOL MessageBeep(UINT uType // 聲音類型
                                           ); 

用C#編寫一下原型:

public enum BeepType
{
  SimpleBeep = -1,
  IconAsterisk = 0x00000040,
  IconExclamation = 0x00000030,
  IconHand = 0x00000010,
  IconQuestion = 0x00000020,
  Ok = 0x00000000,
} 

uType 參數實際上接受一組預先定義的常量,對於 uType 參數,使用 enum 類型是合乎情理的。

[DllImport("user32.dll")]
public static extern bool MessageBeep(BeepType beepType);  


示例三:處理結構
    如果需要確定筆記本的電池狀況。Win32 為此提供了電源管理函數,搜索 MSDN 可以找到GetSystemPowerStatus() 函數。 
  

  BOOL GetSystemPowerStatus( 
                              LPSYSTEM_POWER_STATUS lpSystemPowerStatus 
                             );

    此函數包含指向某個結構的指針,我們尚未對此進行過處理。要處理結構,我們需要用 C# 定義結構。我們從非托管的定義開始: 

typedef struct _SYSTEM_POWER_STATUS { 
   BYTE  ACLineStatus; 
   BYTE  BatteryFlag; 
   BYTE  BatteryLifePercent; 
   BYTE  Reserved1; 
   DWORD BatteryLifeTime; 
   DWORD BatteryFullLifeTime; 
} SYSTEM_POWER_STATUS, *LPSYSTEM_POWER_STATUS; 

   然後,通過用 C# 類型代替 C 類型來得到 C# 版本。 

struct SystemPowerStatus 
{ 
  byte ACLineStatus; 
  byte batteryFlag; 
  byte batteryLifePercent; 
  byte reserved1; 
  int batteryLifeTime; 
  int batteryFullLifeTime; 
} 

    這樣,就可以方便地編寫出 C# 原型: 

[DllImport("kernel32.dll")] 
public static extern bool GetSystemPowerStatus( ref SystemPowerStatus systemPowerStatus); 

   在此原型中,我們用 “ref” 指明將傳遞結構指針而不是結構值。這是處理通過指針傳遞的結構的一般方法。 
   此函數運行良好,但是最好將 ACLineStatus 和 batteryFlag 字段定義為 enum: 

    enum ACLineStatus: byte 
   { 
    Offline = 0, 
    Online = 1, 
    Unknown = 255, 
   } 
   enum BatteryFlag: byte 
   { 
    High = 1, 
    Low = 2, 
    Critical = 4, 
    Charging = 8, 
    NoSystemBattery = 128, 
    Unknown = 255, 
   } 

請注意,由於結構的字段是一些字節,因此我們使用 byte 作為該 enum 的基本類型

示例四:處理字符串


二 C# 中調用C++代碼
    int 類型 

[DllImport(“MyDLL.dll")] 
//返回個int 類型 
public static extern int mySum (int a1,int b1); 
//DLL中申明 
extern “C” __declspec(dllexport)  int WINAPI mySum(int a2,int b2) 
{ 
//a2 b2不能改變a1 b1
//a2=..
//b2=...
 return a+b; 
} 
//參數傳遞int 類型 
public static extern int mySum (ref int a1,ref int b1); 
//DLL中申明 
extern “C” __declspec(dllexport)  int WINAPI mySum(int *a2,int *b2) 
{ 
//可以改變 a1, b1
*a2=...
*b2=...
 return a+b; 
} 

DLL 需傳入char *類型 

[DllImport(“MyDLL.dll")] 
//傳入值 
public static extern int mySum (string  astr1,string bstr1); 
//DLL中申明 
extern “C” __declspec(dllexport)  int WINAPI mySum(char * astr2,char * bstr2) 
{ 
//改變astr2 bstr 2  ,astr1 bstr1不會被改變
 return a+b; 
}


DLL 需傳出char *類型 

[DllImport(“MyDLL.dll")] 
// 傳出值
public static extern int mySum (StringBuilder abuf, StringBuilder bbuf ); 
//DLL中申明 
extern “C” __declspec(dllexport)  int WINAPI mySum(char * astr,char * bstr) 
{ 
//傳出char * 改變astr bstr -->abuf, bbuf可以被改變
 return a+b; 
} 

DLL 回調函數 

BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam) 
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("Window handle is "); 
        Console.WriteLine(hwnd); return true; 
     } 
} 

DLL  傳遞結構  

BOOL PtInRect(const RECT *lprc, POINT pt); 
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 XXXX { [DllImport("User32.dll")] public static extern bool PtInRect(ref Rect r, Point p); }

 



  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved