![](/img/trans.png)
[英]C++ dll Pinvoke function with function pointer struct in parameter
[英]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.