欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#實(shí)現(xiàn)Struct結(jié)構(gòu)體與IntPtr轉(zhuǎn)換的示例詳解

 更新時(shí)間:2025年06月05日 10:25:45   作者:阿蒙Armon  
在 C# 編程的世界里,我們常常會(huì)遇到需要與非托管代碼交互,或者進(jìn)行一些底層內(nèi)存操作的場(chǎng)景,下面小編就來(lái)分享兩段非常實(shí)用的 C# 擴(kuò)展方法代碼,它們實(shí)現(xiàn)了結(jié)構(gòu)體與IntPtr之間的轉(zhuǎn)換等功能

在 C# 編程的世界里,我們常常會(huì)遇到需要與非托管代碼交互,或者進(jìn)行一些底層內(nèi)存操作的場(chǎng)景。這時(shí),IntPtr類(lèi)型就顯得尤為重要,它可以表示一個(gè)指針或句柄,用來(lái)指向非托管內(nèi)存中的數(shù)據(jù)。而結(jié)構(gòu)體作為一種常用的數(shù)據(jù)結(jié)構(gòu),在與IntPtr進(jìn)行數(shù)據(jù)傳遞和轉(zhuǎn)換時(shí),往往需要一些繁瑣的操作。為了簡(jiǎn)化這些操作,提高開(kāi)發(fā)效率,我們可以通過(guò)擴(kuò)展方法來(lái)封裝相關(guān)的功能。接下來(lái),就為大家介紹兩段非常實(shí)用的 C# 擴(kuò)展方法代碼,它們實(shí)現(xiàn)了結(jié)構(gòu)體與IntPtr之間的轉(zhuǎn)換等功能。

一、代碼概覽

我們有兩個(gè)擴(kuò)展方法類(lèi),分別是StructExtensions和IntPtrExtensions。StructExtensions類(lèi)主要提供將結(jié)構(gòu)體和結(jié)構(gòu)體數(shù)組轉(zhuǎn)換為IntPtr的方法;IntPtrExtensions類(lèi)則提供了將IntPtr轉(zhuǎn)換回結(jié)構(gòu)體、將IntPtr指向的內(nèi)存數(shù)據(jù)轉(zhuǎn)換為字節(jié)數(shù)組,以及釋放IntPtr所占用的非托管內(nèi)存的方法。

1. StructExtensions 類(lèi)

using System;
using System.Runtime.InteropServices;

public static class StructExtensions
{
    /// <summary>
    /// struct to IntPtr
    /// IntPtr使用完,需釋放
    /// </summary>
    /// <typeparam name="T">struct</typeparam>
    /// <param name="value">struct值</param>
    /// <returns>IntPtr</returns>
    public static IntPtr ToIntPtr<T>(this T value) where T : struct
    {
        var intptr = Marshal.AllocHGlobal(Marshal.SizeOf(value));
        Marshal.StructureToPtr(value, intptr, true);
        return intptr;
    }

    /// <summary>
    /// struct[] to IntPtr
    /// IntPtr使用完,需釋放
    /// </summary>
    /// <typeparam name="T">struct</typeparam>
    /// <param name="value">struct[]值</param>
    /// <returns>IntPtr</returns>
    public static IntPtr ToIntPtr<T>(this T[] value) where T : struct
    {
        var intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(T)) * value.Length);
        var longPtr = intPtr.ToInt64();
        for (var i = 0; i < value.Length; i++)
        {
            var rectPtr = new IntPtr(longPtr);
            Marshal.StructureToPtr(value[i], rectPtr, false);
            longPtr += Marshal.SizeOf(typeof(T));
        }
        return new IntPtr(longPtr);
    }
}

在這個(gè)類(lèi)中,第一個(gè)ToIntPtr方法接受一個(gè)結(jié)構(gòu)體類(lèi)型的參數(shù)value,首先使用Marshal.AllocHGlobal方法在非托管內(nèi)存中分配足夠的空間,空間大小由Marshal.SizeOf(value)確定,即結(jié)構(gòu)體實(shí)例的大小。然后通過(guò)Marshal.StructureToPtr方法將結(jié)構(gòu)體實(shí)例的值復(fù)制到分配的非托管內(nèi)存中,并返回指向該內(nèi)存的IntPtr。需要注意的是,使用完返回的IntPtr后,必須釋放其占用的內(nèi)存,否則會(huì)導(dǎo)致內(nèi)存泄漏。

第二個(gè)ToIntPtr方法則是針對(duì)結(jié)構(gòu)體數(shù)組,它根據(jù)數(shù)組的長(zhǎng)度和單個(gè)結(jié)構(gòu)體的大小,在非托管內(nèi)存中分配相應(yīng)大小的空間,并返回指向該內(nèi)存的IntPtr。不過(guò),此方法只是分配了內(nèi)存,并沒(méi)有將數(shù)組中的數(shù)據(jù)復(fù)制到內(nèi)存中,如果需要復(fù)制數(shù)據(jù),還需要進(jìn)一步的操作。

2. IntPtrExtensions 類(lèi)

using System;
using System.Runtime.InteropServices;

public static class IntPtrExtensions
{
    public static T ToStructure<T>(this IntPtr value) where T : struct
    {
        return (T)Marshal.PtrToStructure(value, typeof(T));
    }

    public static byte[] ToBytes(this IntPtr value, int size)
    {
        var bytes = new byte[size];
        Marshal.Copy(value, bytes, 0, size);
        return bytes;
    }

    public static void Free(ref this IntPtr value)
    {
        Marshal.FreeHGlobal(value);
    }
}

IntPtrExtensions類(lèi)中的ToStructure方法,接受一個(gè)IntPtr類(lèi)型的參數(shù)value,通過(guò)Marshal.PtrToStructure方法將IntPtr指向的非托管內(nèi)存中的數(shù)據(jù)轉(zhuǎn)換為指定的結(jié)構(gòu)體類(lèi)型,并返回轉(zhuǎn)換后的結(jié)構(gòu)體實(shí)例。

ToBytes方法將IntPtr指向的內(nèi)存中的數(shù)據(jù)讀取到一個(gè)字節(jié)數(shù)組中。它接受一個(gè)表示內(nèi)存大小的參數(shù)size,首先創(chuàng)建一個(gè)指定大小的字節(jié)數(shù)組,然后使用Marshal.Copy方法將IntPtr指向的內(nèi)存數(shù)據(jù)復(fù)制到字節(jié)數(shù)組中,并返回該字節(jié)數(shù)組。

Free方法用于釋放IntPtr所占用的非托管內(nèi)存,通過(guò)Marshal.FreeHGlobal方法來(lái)實(shí)現(xiàn)內(nèi)存的釋放,由于需要修改IntPtr本身,所以參數(shù)使用了ref關(guān)鍵字。

二、使用示例

下面我們通過(guò)一個(gè)簡(jiǎn)單的示例來(lái)展示這些擴(kuò)展方法的具體使用:

using System;
using System.Runtime.InteropServices;

struct Point
{
   public int X;
   public int Y;
}


class Program
{
   static void Main()
   {
       var point = new Point { X = 10, Y = 20 };

       // 將結(jié)構(gòu)體轉(zhuǎn)換為IntPtr
       var intPtr = point.ToIntPtr();

       // 將IntPtr轉(zhuǎn)換回結(jié)構(gòu)體
       var newPoint = intPtr.ToStructure<Point>();


       Console.WriteLine($"X: {newPoint.X}, Y: {newPoint.Y}");


       // 釋放IntPtr占用的內(nèi)存
       intPtr.Free();
       
       
       var points = { new Point { X = 1, Y = 2 }, new Point { X = 3, Y = 4 } };
       // 將結(jié)構(gòu)體數(shù)組轉(zhuǎn)換為IntPtr
       var arrayIntPtr = points.ToIntPtr();


       // 這里可以添加將數(shù)組數(shù)據(jù)復(fù)制到內(nèi)存的操作

       // 釋放IntPtr占用的內(nèi)存
       arrayIntPtr.Free();
   }


}

在這個(gè)示例中,我們定義了一個(gè)Point結(jié)構(gòu)體,然后分別演示了將結(jié)構(gòu)體和結(jié)構(gòu)體數(shù)組轉(zhuǎn)換為IntPtr,再將IntPtr轉(zhuǎn)換回結(jié)構(gòu)體,以及釋放IntPtr所占用內(nèi)存的整個(gè)過(guò)程。

三、注意事項(xiàng)

1.內(nèi)存管理:正如前面多次提到的,使用Marshal.AllocHGlobal分配的非托管內(nèi)存必須手動(dòng)釋放,否則會(huì)造成內(nèi)存泄漏。在實(shí)際應(yīng)用中,要確保在合適的時(shí)機(jī)調(diào)用Free方法。

.2數(shù)據(jù)一致性:在將結(jié)構(gòu)體數(shù)組轉(zhuǎn)換為IntPtr時(shí),如果需要將數(shù)組數(shù)據(jù)復(fù)制到內(nèi)存中,需要額外編寫(xiě)代碼實(shí)現(xiàn),否則IntPtr指向的內(nèi)存中數(shù)據(jù)是未初始化的。

3.類(lèi)型安全:在使用ToStructure方法時(shí),要確保IntPtr指向的內(nèi)存中的數(shù)據(jù)與目標(biāo)結(jié)構(gòu)體類(lèi)型一致,否則可能會(huì)導(dǎo)致類(lèi)型轉(zhuǎn)換錯(cuò)誤或程序異常。

通過(guò)這些實(shí)用的擴(kuò)展方法,我們可以更加便捷地在 C# 中處理結(jié)構(gòu)體與IntPtr之間的數(shù)據(jù)轉(zhuǎn)換和內(nèi)存操作,提高代碼的可讀性和可維護(hù)性。

到此這篇關(guān)于C#實(shí)現(xiàn)Struct結(jié)構(gòu)體與IntPtr轉(zhuǎn)換的示例詳解的文章就介紹到這了,更多相關(guān)C# Struct結(jié)構(gòu)體轉(zhuǎn)IntPtr內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C#連接數(shù)據(jù)庫(kù)的幾種方法

    C#連接數(shù)據(jù)庫(kù)的幾種方法

    這篇文章介紹了C#連接數(shù)據(jù)庫(kù)的幾種方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • 基于C#實(shí)現(xiàn)自定義計(jì)算的Excel數(shù)據(jù)透視表

    基于C#實(shí)現(xiàn)自定義計(jì)算的Excel數(shù)據(jù)透視表

    數(shù)據(jù)透視表(Pivot?Table)是一種數(shù)據(jù)分析工具,通常用于對(duì)大量數(shù)據(jù)進(jìn)行匯總、分析和展示,本文主要介紹了C#實(shí)現(xiàn)自定義計(jì)算的Excel數(shù)據(jù)透視表的相關(guān)知識(shí),感興趣的可以了解下
    2023-12-12
  • C# 前端無(wú)插件打印導(dǎo)出實(shí)現(xiàn)方式詳解

    C# 前端無(wú)插件打印導(dǎo)出實(shí)現(xiàn)方式詳解

    本文講述了使用C#實(shí)現(xiàn)前端無(wú)插件的打印和導(dǎo)出功能,介紹了相關(guān)技術(shù)和方法,適合需要在項(xiàng)目中實(shí)現(xiàn)相應(yīng)功能的開(kāi)發(fā)者參考
    2024-10-10
  • c#數(shù)據(jù)綁定之將datatabel的data添加listView

    c#數(shù)據(jù)綁定之將datatabel的data添加listView

    這篇文章主要介紹了c#將DataTabel的data添加ListView的示例,實(shí)現(xiàn)功能是通過(guò)響應(yīng)UI Textbox 的值向ListView 綁定新添加的紀(jì)錄。 ,需要的朋友可以參考下
    2014-04-04
  • 利用C#實(shí)現(xiàn)分割GIF圖片

    利用C#實(shí)現(xiàn)分割GIF圖片

    這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)分割GIF圖片的功能,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以了解一下
    2022-12-12
  • 一篇文章說(shuō)通C#的屬性Attribute

    一篇文章說(shuō)通C#的屬性Attribute

    這篇文章主要給大家介紹了如何通過(guò)一篇文章說(shuō)通C#的屬性Attribute,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Unity實(shí)現(xiàn)簡(jiǎn)單虛擬搖桿

    Unity實(shí)現(xiàn)簡(jiǎn)單虛擬搖桿

    這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)簡(jiǎn)單虛擬搖桿,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C#訪(fǎng)問(wèn)PostGreSQL數(shù)據(jù)庫(kù)的方法

    C#訪(fǎng)問(wèn)PostGreSQL數(shù)據(jù)庫(kù)的方法

    這次的項(xiàng)目中的一個(gè)環(huán)節(jié)要求我把PostGreSQL數(shù)據(jù)取出來(lái),然后放到SqlServer里,再去處理分析。
    2013-04-04
  • C# 使用 OleDbConnection 連接讀取Excel的方法

    C# 使用 OleDbConnection 連接讀取Excel的方法

    這篇文章主要介紹了C# 使用 OleDbConnection 連接讀取Excel的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • C#中Winform窗體Form的關(guān)閉按鈕變灰色的方法

    C#中Winform窗體Form的關(guān)閉按鈕變灰色的方法

    這篇文章主要介紹了C#中Winform窗體Form的關(guān)閉按鈕變灰色的方法,對(duì)于C#程序界面的設(shè)計(jì)有一定的借鑒價(jià)值,需要的朋友可以參考下
    2014-08-08

最新評(píng)論