簡體   English   中英

Pinvoke:將新的結構指針傳遞給超出結構大小的 function

[英]Pinvoke: passing a new struct pointer to a function which outs the size of the struct

我有以下 function 的原型: https://docs.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-GetUrlCacheGroupAttributeA

看起來像這樣:

[DllImport("wininet", SetLastError = true, CharSet = CharSet.Auto, EntryPoint = "GetUrlCacheGroupAttributeA", CallingConvention = CallingConvention.StdCall)]
private static extern bool GetUrlCacheGroupAttribute(
        long gid,
        uint dwFlags,
        uint dwAttributes,
        IntPtr lpGroupInfo,
        ref uint lpcbGroupInfo,
        IntPtr lpReserved);

lpdwGroupInfo作為out而不是ref可能更有意義,但除此之外,我認為這是正確的。

我不明白的是,我應該如何傳遞一個指向INTERNET_CACHE_GROUP_INFO結構lpGroupInfo的指針(我也已經定義/原型化了這個函數)。 我知道其他所有內容是如何傳入的,只是這個指針讓我感到困惑。

function 對指針的狀態如下:

lpGroupInfo - 指向接收請求信息的 INTERNET_CACHE_GROUP_INFO 結構的指針。

lpcbGroupInfo - 指向包含 lpGroupInfo 緩沖區大小的變量的指針。 當 function 返回時,該變量包含復制到緩沖區的字節數,或緩沖區所需的大小,以字節為單位。

我需要通過Marshal.AllocHGlobal或其他方式分配 memory 嗎? 這似乎表明我只會在傳入結構后才獲得結構的大小,但是如果沒有首先定義它,我該如何傳入呢? 我完全不清楚如何創建初始指針,以及我期望如何Marshal.PtrToStructure它。

西蒙的評論回答了我的問題:

對於結構緩沖區指針作為參數傳入的函數(旨在由函數修改),並且由於緩沖區大小不足而失敗時它也超出了所需的緩沖區大小,使用這些函數的正確方法是傳入這些初始化為默認值的值(IntPtr.Zero 和 0),然后當 function 失敗時(您可以確認錯誤是由於緩沖區大小引起的),它將設置所需的緩沖區大小,您可以調用 function再次將 memory 分配給指針后。

這是一個示例片段:

        private static void ClearUrlCacheGroups()
        {
            IntPtr enumHandle = FindFirstUrlCacheGroup(0, CACHEGROUP_SEARCH_ALL, IntPtr.Zero, 0, out long lpGroupId, IntPtr.Zero);

            if (enumHandle != IntPtr.Zero)
            {
                bool foundNextGroup;
                bool isDeleted;
                uint cacheGroupInfoBufferSize = 0;
                IntPtr cacheGroupInfoBuffer = Marshal.AllocHGlobal((IntPtr)cacheGroupInfoBufferSize);

                do
                {
                    bool getAttributeSucceeded = GetUrlCacheGroupAttribute(lpGroupId, 0, CACHEGROUP_ATTRIBUTE_GET_ALL, cacheGroupInfoBuffer, ref cacheGroupInfoBufferSize, IntPtr.Zero);

                    if (!getAttributeSucceeded && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
                    {
                        cacheGroupInfoBuffer = Marshal.ReAllocHGlobal(cacheGroupInfoBuffer, (IntPtr)cacheGroupInfoBufferSize);
                        getAttributeSucceeded = GetUrlCacheGroupAttribute(lpGroupId, 0, CACHEGROUP_ATTRIBUTE_GET_ALL, cacheGroupInfoBuffer, ref cacheGroupInfoBufferSize, IntPtr.Zero);
                    }

                    if (getAttributeSucceeded)
                    {
                        INTERNET_CACHE_GROUP_INFOA internetCacheEntry = (INTERNET_CACHE_GROUP_INFOA)Marshal.PtrToStructure(cacheGroupInfoBuffer, typeof(INTERNET_CACHE_GROUP_INFOA));
                    }

                    isDeleted = DeleteUrlCacheGroup(lpGroupId, CACHEGROUP_FLAG_FLUSHURL_ONDELETE, IntPtr.Zero);
                    foundNextGroup = FindNextUrlCacheGroup(enumHandle, ref lpGroupId, IntPtr.Zero);
                }
                while (foundNextGroup);

                Marshal.FreeHGlobal(cacheGroupInfoBuffer);
            }
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM