国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

創建Win32 DLL,并在C#里面調用

2024-07-21 02:26:53
字體:
來源:轉載
供稿:網友

這是三篇網上收集的技術文章的合集,分別講解了如何創建win32 dll,然后如何在c#里面調用這個dll的教程。

首先是創建win32 dll的文章。講解這個的文章到處都有,這里給出一篇我看過的:http://www.flipcode.com/articles/article_creatingdlls.shtml。win32 dll的創建其實在visual studio里面已經給出了比較好的模板,只是需要注意的,有些xxx_api宏并沒有把extern "c"加進去,這樣會造成在c#里面找不到這個函數的錯誤。所以,請記住,一定要把函數定義extern "c"。


第二篇文章來之于http://edu.100down.com/it/program/csharp/105256797.html,下面是轉貼內容:

平臺調用服務 (pinvoke) 允許托管代碼調用在 dll 中實現的非托管函數。

本教程說明使用什么方法才能從 c# 調用非托管 dll 函數。該教程所討論的屬性允許您調用這些函數并使數據類型得到正確封送。

教程

c# 代碼有以下兩種可以直接調用非托管代碼的方法:

  • 直接調用從 dll 導出的函數。
  • 調用 com 對象上的接口方法(有關更多信息,請參見 com interop 第一部分:c# 客戶端教程)。

對于這兩種技術,都必須向 c# 編譯器提供非托管函數的聲明,并且還可能需要向 c# 編譯器提供如何封送與非托管代碼之間傳遞的參數和返回值的說明。

該教程由下列主題組成:

  • 直接從 c# 調用 dll 導出
  • 默認封送處理和為非托管方法的參數指定自定義封送處理
  • 為用戶定義的結構指定自定義封送處理
  • 注冊回調方法

該教程包括下列示例:

  • 示例 1 使用 dllimport
  • 示例 2 重寫默認封送處理
  • 示例 3 指定自定義封送處理

直接從 c# 調用 dll 導出

若要聲明一個方法使其具有來自 dll 導出的實現,請執行下列操作:

  • 使用 c# 關鍵字 staticextern 聲明方法。
  • dllimport 屬性附加到該方法。dllimport 屬性允許您指定包含該方法的 dll 的名稱。通常的做法是用與導出的方法相同的名稱命名 c# 方法,但也可以對 c# 方法使用不同的名稱。
  • 還可以為方法的參數和返回值指定自定義封送處理信息,這將重寫 .net framework 的默認封送處理。

示例 1

本示例顯示如何使用 dllimport 屬性通過調用 msvcrt.dll 中的 puts 輸出消息。

// pinvoketest.csusing system;using system.runtime.interopservices;class platforminvoketest{    [dllimport("msvcrt.dll")]    public static extern int puts(string c);    [dllimport("msvcrt.dll")]    internal static extern int _flushall();    public static void main()     {        puts("test");        _flushall();    }}

輸出

test

代碼討論

前面的示例顯示了聲明在非托管 dll 中實現的 c# 方法的最低要求。platforminvoketest.puts 方法用 staticextern 修飾符聲明并且具有 dllimport 屬性,該屬性使用默認名稱 puts 通知編譯器此實現來自 msvcrt.dll。若要對 c# 方法使用不同的名稱(如 putstring),則必須在 dllimport 屬性中使用 entrypoint 選項,如下所示:

[dllimport("msvcrt.dll", entrypoint="puts")]

有關 dllimport 屬性的語法的更多信息,請參見 dllimportattribute 類。

默認封送處理和為非托管方法的參數指定自定義封送處理

當從 c# 代碼中調用非托管函數時,公共語言運行庫必須封送參數和返回值。

對于每個 .net framework 類型均有一個默認非托管類型,公共語言運行庫將使用此非托管類型在托管到非托管的函數調用中封送數據。例如,c# 字符串值的默認封送處理是封送為 lptstr(指向 tchar 字符緩沖區的指針)類型。可以在非托管函數的 c# 聲明中使用 marshalas 屬性重寫默認封送處理。

示例 2

本示例使用 dllimport 屬性輸出一個字符串。它還顯示如何通過使用 marshalas 屬性重寫函數參數的默認封送處理。

// marshal.csusing system;using system.runtime.interopservices;class platforminvoketest{    [dllimport("msvcrt.dll")]    public static extern int puts(        [marshalas(unmanagedtype.lpstr)]        string m);    [dllimport("msvcrt.dll")]    internal static extern int _flushall();    public static void main()     {        puts("hello world!");        _flushall();    }}

輸出

運行此示例時,字符串

hello world!

將顯示在控制臺上。

代碼討論

在前面的示例中,puts 函數的參數的默認封送處理已從默認值 lptstr 重寫為 lpstr。

marshalas 屬性可以放置在方法參數、方法返回值以及結構和類的字段上。若要設置方法返回值的封送處理,請將 marshalas 屬性與返回屬性位置重寫一起放置在方法上的屬性塊中。例如,若要顯式設置 puts 方法返回值的封送處理:

...[dllimport("msvcrt.dll")] [return : marshalas(unmanagedtype.i4)]public static extern int puts( ...

有關 marshalas 屬性的語法的更多信息,請參見 marshalasattribute 類。

注意   inout 屬性可用于批注非托管方法的參數。它們與 midl 源文件中的 inout 修飾符的工作方式類似。請注意,out 屬性與 c# 參數修飾符 out 不同。有關 inout 屬性的更多信息,請參見 inattribute 類和 outattribute 類。

為用戶定義的結構指定自定義封送處理

可以為傳遞到非托管函數或從非托管函數返回的結構和類的字段指定自定義封送處理屬性。通過向結構或類的字段中添加 marshalas 屬性可以做到這一點。還必須使用 structlayout 屬性設置結構的布局,還可以控制字符串成員的默認封送處理,并設置默認封裝大小。

示例 3

本示例說明如何為結構指定自定義封送處理屬性。

請考慮下面的 c 結構:

typedef struct taglogfont {    long lfheight;    long lfwidth;    long lfescapement;    long lforientation;    long lfweight;    byte lfitalic;    byte lfunderline;    byte lfstrikeout;    byte lfcharset;    byte lfoutprecision;    byte lfclipprecision;    byte lfquality;    byte lfpitchandfamily;    tchar lffacename[lf_facesize]; } logfont; 

在 c# 中,可以使用 structlayoutmarshalas 屬性描述前面的結構,如下所示:

// logfont.cs// compile with: /target:moduleusing system;using system.runtime.interopservices;[structlayout(layoutkind.sequential)]public class logfont {     public const int lf_facesize = 32;    public int lfheight;     public int lfwidth;     public int lfescapement;     public int lforientation;     public int lfweight;     public byte lfitalic;     public byte lfunderline;     public byte lfstrikeout;     public byte lfcharset;     public byte lfoutprecision;     public byte lfclipprecision;     public byte lfquality;     public byte lfpitchandfamily;    [marshalas(unmanagedtype.byvaltstr, sizeconst=lf_facesize)]    public string lffacename; }

有關 structlayout 屬性的語法的更多信息,請參見 structlayoutattribute 類。

然后即可將該結構用在 c# 代碼中,如下所示:

// pinvoke.cs// compile with: /addmodule:logfont.netmoduleusing system;using system.runtime.interopservices; class platforminvoketest{         [dllimport("gdi32.dll", charset=charset.auto)]      public static extern intptr createfontindirect(            [in, marshalas(unmanagedtype.lpstruct)]            logfont lplf   // characteristics            );       [dllimport("gdi32.dll")]      public static extern bool deleteobject(            intptr handle            );       public static void main()       {            logfont lf = new logfont();            lf.lfheight = 9;            lf.lffacename = "arial";            intptr handle = createfontindirect(lf);             if (intptr.zero == handle)            {                  console.writeline("can't creates a logical font.");            }            else            {                                    if (intptr.size == 4)                        console.writeline("{0:x}", handle.toint32());                  else                        console.writeline("{0:x}", handle.toint64());                           // delete the logical font created.                  if (!deleteobject(handle))                       console.writeline("can't delete the logical font");            }      }}

運行示例

c30a0ae5

代碼討論

在前面的示例中,createfontindirect 方法使用了一個 logfont 類型的參數。marshalasin 屬性用于限定此參數。程序將由此方法返回的數值顯示為十六進制大寫字符串。

注冊回調方法

若要注冊調用非托管函數的托管回調,請用相同的參數列表聲明一個委托并通過 pinvoke 傳遞它的一個實例。在非托管端,它將顯示為一個函數指針。有關 pinvoke 和回調的更多信息,請參見平臺調用詳解。

例如,考慮以下非托管函數 myfunction,此函數要求 callback 作為其參數之一:

typedef void (__stdcall *pfn_mycallback)();int __stdcall myfunction(pfn_ mycallback callback);

若要從托管代碼調用 myfunction,請聲明該委托,將 dllimport 附加到函數聲明,并根據需要封送任何參數或返回值:

public delegate void mycallback();[dllimport("mydll.dll")]public static extern void myfunction(mycallback callback);

同時,請確保委托實例的生存期覆蓋非托管代碼的生存期;否則,委托在經過垃圾回收后將不再可用。


 第三篇文章來之于http://www.njpro.cn/8918/showpost.aspx,一篇關于c/c++和c#中的數據類型的對應表。

wtypes.h 中的非托管類型非托管 c 語言類型托管類名說明
handlevoid*system.intptr32 位
byteunsigned charsystem.byte8 位
shortshortsystem.int1616 位
wordunsigned shortsystem.uint1616 位
intintsystem.int3232 位
uintunsigned intsystem.uint3232 位
longlongsystem.int3232 位
boollongsystem.int3232 位
dwordunsigned longsystem.uint3232 位
ulongunsigned longsystem.uint3232 位
charcharsystem.char用 ansi 修飾。
lpstrchar*system.stringsystem.stringbuilder用 ansi 修飾。
lpcstrconst char*system.stringsystem.stringbuilder用 ansi 修飾。
lpwstrwchar_t*system.stringsystem.stringbuilder用 unicode 修飾。
lpcwstrconst wchar_t*system.stringsystem.stringbuilder用 unicode 修飾。
floatfloatsystem.single32 位
doubledouble

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 石楼县| 临江市| 崇礼县| 疏附县| 蓬安县| 伊川县| 八宿县| 富顺县| 佳木斯市| 包头市| 上蔡县| 萍乡市| 剑河县| 游戏| 新巴尔虎右旗| 灯塔市| 运城市| 太保市| 府谷县| 田阳县| 宜都市| 乌拉特中旗| 准格尔旗| 朝阳市| 娄烦县| 廉江市| 铜川市| 和林格尔县| 洛宁县| 南昌市| 牙克石市| 高要市| 莱州市| 宁国市| 灌云县| 积石山| 荣成市| 蓬安县| 青川县| 黔西| 宁武县|