最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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ù)結(jié)構(gòu)之隊(duì)列(Quene)實(shí)例詳解

    C#數(shù)據(jù)結(jié)構(gòu)之隊(duì)列(Quene)實(shí)例詳解

    這篇文章主要介紹了C#數(shù)據(jù)結(jié)構(gòu)之隊(duì)列(Quene),結(jié)合實(shí)例形式較為詳細(xì)的講述了隊(duì)列的功能、原理與C#實(shí)現(xiàn)隊(duì)列的相關(guān)技巧,需要的朋友可以參考下
    2015-11-11
  • c#入門(mén)之類(lèi)型轉(zhuǎn)換詳解

    c#入門(mén)之類(lèi)型轉(zhuǎn)換詳解

    這篇文章主要介紹了c#的類(lèi)型轉(zhuǎn)換詳解,類(lèi)型轉(zhuǎn)換分兩種形式:隱式轉(zhuǎn)換、顯示轉(zhuǎn)換,下面是詳細(xì)介紹
    2014-04-04
  • unity實(shí)現(xiàn)攝像頭跟隨

    unity實(shí)現(xiàn)攝像頭跟隨

    把這個(gè)腳本賦給你的攝像機(jī),再把游戲角色賦給character變量,之后就能實(shí)現(xiàn)攝像機(jī)平滑的跟隨player在地球的任一角落了。有需要的小伙伴可以參考下。
    2015-03-03
  • C#組合模式實(shí)例詳解

    C#組合模式實(shí)例詳解

    這篇文章主要介紹了C#組合模式,實(shí)例分析了C#實(shí)現(xiàn)組合模式的原理與相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • C#實(shí)現(xiàn)在PDF文檔中應(yīng)用多種不同字體

    C#實(shí)現(xiàn)在PDF文檔中應(yīng)用多種不同字體

    在PDF文檔中,可繪制不同字體樣式、不同語(yǔ)言的文字,可通過(guò)使用Standard字體、TrueType字體、CJK字體或者自定義(私有)等字體類(lèi)型。本文將具體介紹實(shí)現(xiàn)的方法,需要的可以參考一下
    2022-01-01
  • C#程序員應(yīng)該養(yǎng)成的程序性能優(yōu)化寫(xiě)法

    C#程序員應(yīng)該養(yǎng)成的程序性能優(yōu)化寫(xiě)法

    工作和生活中經(jīng)??梢钥吹揭恍┏绦蛟?寫(xiě)代碼的時(shí)候只關(guān)注代碼的邏輯性,而不考慮運(yùn)行效率,其實(shí)這對(duì)大多數(shù)程序猿來(lái)說(shuō)都是沒(méi)有問(wèn)題的,不過(guò)作為一只有理想的CodeMonkey,我還是希望給大家分享一些性能優(yōu)化心得
    2017-08-08
  • C#實(shí)現(xiàn)汽車(chē)租賃系統(tǒng)項(xiàng)目

    C#實(shí)現(xiàn)汽車(chē)租賃系統(tǒng)項(xiàng)目

    這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)汽車(chē)租賃系統(tǒng)項(xiàng)目,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • c# 圓形識(shí)別方案和直線識(shí)別方案的參考示例

    c# 圓形識(shí)別方案和直線識(shí)別方案的參考示例

    這篇文章主要介紹了c# 圓形識(shí)別方案和直線識(shí)別方案的實(shí)現(xiàn)示例,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-03-03
  • C#接口(Interface)用法分析

    C#接口(Interface)用法分析

    這篇文章主要介紹了C#接口(Interface)用法,較為詳細(xì)的分析了C#中接口的功能、實(shí)現(xiàn)及使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03
  • C# 結(jié)合 Javascript 測(cè)試獲取天氣信息

    C# 結(jié)合 Javascript 測(cè)試獲取天氣信息

    本文將介紹如何使用 C# 并結(jié)合 JavaScript 獲取天氣信息,獲取的數(shù)據(jù)來(lái)源于360瀏覽器首頁(yè)數(shù)據(jù),對(duì)C# 獲取天氣信息示例代碼感興趣的朋友一起看看吧
    2024-08-08

最新評(píng)論

成安县| 佛山市| 宁海县| 新丰县| 山西省| 沐川县| 宁津县| 隆德县| 柘城县| 苏尼特左旗| 通化县| 加查县| 黎平县| 融水| 兰州市| 买车| 图片| 大连市| 临江市| 虹口区| 珲春市| 兴宁市| 长沙县| 郑州市| 衡南县| 海兴县| 罗城| 云阳县| 奉化市| 客服| 景泰县| 安龙县| 西华县| 灵武市| 福州市| 延寿县| 石嘴山市| 连平县| 河西区| 淮南市| 且末县|