C#和記憶體指標

來源:互聯網
上載者:User

C#和記憶體指標
來源:qqread 作者: 出處:巧巧讀書 2007-03-16 進入討論群組
關 鍵 詞: serverword.net 
 
雖然到了.net  的runtime  時代,C  仍然是不可磨滅的主要支柱,包括在MSDN  裡見到的API  大部都是有指標類型存在,那麼在以C  冠首的C#  裡應當如何去使用指標呢?  
其實,C#  裡可以直接使用結構型的變數引用進API,但是畢竟它不是指標在對一些涉及以結構數組存放的記憶體區操作可能就力有不及了,我舉一個例子要使用到結構數組的一個API(對這個API  不必加以瞭解,我們不是主說API): 
net_api_status  netshareenum(
LPWSTR  servername,
DWORD  level,
LPBYTE*  bufptr,
DWORD  prefmaxlen,
LPDWORD  entriesread,
LPDWORD  totalentries,
LPDWORD  resume_handle
);

及它要用到的結構  (設  level  為1):

typedef  struct  _share_info_1  {
LPWSTR  shi1_netname;
DWORD  shi1_type;
LPWSTR  shi1_remark;
}  SHARE_INFO_1,  *PSHARE_INFO_1,  *LPSHARE_INFO_1;

在第三個參數  LPBYTE*  bufptr  它就是一個指標,而非C  型傳統語言的數組的做法,就可以直接聲明成  ref  SHARE_INFO_1[]  bufptr,但我不推薦這麼做,原因之一在C#  似乎還不支援結構數組塊,而且它並沒有存在數組型結構參數的重載。暫且不說如何去實現它,我希望以  C  的操作方式-指標去實現,所以我轉成  C#  聲明如下:

[structlayout(layoutkind.sequential)]
protected  struct  SHARE_INFO_1  {
[MarshalAs(UnmanagedType.LPWStr)]  public  string  shi1_netname;
[MarshalAs(UnmanagedType.U4)]  public  uint  shi1_type;
[MarshalAs(UnmanagedType.LPWStr)]  public  string  shi1_remark;
}

[dllimport("netapi32.dll",  entrypoint="netshareenum")]
protected  static  extern  int  NetShareEnum(
[MarshalAs(UnmanagedType.LPWStr)]  string  servername,
[MarshalAs(UnmanagedType.U4)]  uint  level,
ref  IntPtr  bufptr,
[MarshalAs(UnmanagedType.U4)]  uint  prefmaxlen,
[MarshalAs(UnmanagedType.U4)]  ref  uint  entriesread,
[MarshalAs(UnmanagedType.U4)]  ref  uint  totalentries,
[MarshalAs(UnmanagedType.U4)]  ref  uint  resume_handle
);

在上面的函數執行完成後,會在指標  bufptr  所指的位置存在一個資料區塊,此記憶體塊的資料格式是以  share_info_1  結構排列的(假設level為1),並且在  entriesread  中指示該塊的結構個數,那麼我們要如何將它轉成真正可用的類型到  share_info_1[]  shareinfo;  變數中去呢,其實  c#  提供了一種  marshal.ptrtostructure  的方法,它就是專門將指標所指的非託管記憶體塊搬到託管記憶體中的指定的結構中去,可它不支援結構數組(目前.net
 1.1  還沒有該重載實現過),所以只好也最好一個一個的搬(而且一個一個搬更形象些),例子如下:

int32  ptr  =  bufptr.toint32();
for  (int  i=0;  i<entriesread;  i++)  {
  //開始將ptr  所指的記憶體塊中搬一個SHARE_INFO_1  結構大小並按SHARE_INFO_1  格式排列的資料到  SHARE_INFO_1  型變數  shareInfo  中去
  SHARE_INFO_1  shareInfo  =  (SHARE_INFO_1)Marshal.PtrToStructure(new  IntPtr(ptr),  typeof(SHARE_INFO_1));  
  ptr  +=  Marshal.SizeOf(shareInfo);  //  這是將指標向後移一個結構位,因為已經移完一個結構了

  //todo:  操作當前的  shareinfo
}

上面的例子很明顯了,bufptr  就是指標,該例子就是將記憶體中的指標所指的記憶體塊(非託管記憶體)以一個指定結構的大小和排列格式移動.net  記憶體(託管記憶體)中的一個變數去,然後將指標向後移一個位置(ptr  +=  marshal.sizeof(shareinfo)),此位置由指標當前位置加上  marshal.sizeof(shareinfo)  也就是已經移完的大小獲得,它的意思其實就是將指標移到已經搬完的資料的後面去準備搬一下結構塊

這個例子只是說明指標的用法,並不是主要說api  對該api  及它的參數不必細加研究

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.