Найти общий размер массива объектов, используя только ссылочный указатель?

#c# #marshalling #wlanapi

#c# #сортировка #wlanapi

Вопрос:

Итак, в качестве обзора, я работаю с Wlanapi, и я довольно новичок в нем (в целом, в native API). Я столкнулся с проблемой преобразования структуры из c в c #. Прямо сейчас у меня есть:

Оригинал:

 typedef struct _WLAN_BSS_LIST {
    DWORD          dwTotalSize;
    DWORD          dwNumberOfItems;
    WLAN_BSS_ENTRY wlanBssEntries[1];
} WLAN_BSS_LIST, *PWLAN_BSS_LIST;
  

Преобразование:

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct WLAN_BSS_LIST 
{
    internal uint             dwTotalSize;
    internal uint             dwNumberOfItems;
    internal WLAN_BSS_ENTRY[] wlanBssEntries;

    internal WLAN_BSS_LIST(IntPtr ppBssList)
    {
        dwNumberOfItems = (uint)Marshal.ReadInt32(ppBssList);
        //I need to set the value of dwTotalSize but I dunno how
        wlanBssEntries = new WLAN_BSS_ENTRY[dwNumberOfItems];

        for (int i = 0; i < dwNumberOfItems; i  )
        {
            IntPtr pWlanBssEntry = new IntPtr(ppBssList.ToInt32()   i * 
                Marshal.SizeOf(typeof(WLAN_BSS_ENTRY))   8);
            wlanBssEntries[i] = (WLAN_BSS_ENTRY)Marshal.
                                    PtrToStructure(pWlanBssEntry, 
                                        typeof(WLAN_BSS_ENTRY));
        }
    }
}
  

Я просто не знаю, как получить общий размер массива, на который ссылается ppBssList : (

К вашему сведению, я буду крайне разочарован, если кто-нибудь укажет мне на существующую библиотеку.

Отредактировано для добавления оригинальной структуры

Комментарии:

1. Существует существующая библиотека. managedwifi.codeplex.com

Ответ №1:

Я не уверен, отражает ли ваш twTotalSize объем памяти, выделенный для записей в wlanBssEntries, если да, то простого вычисления было бы достаточно,

  sizeof(typeof(WLAN_BSS_ENTRY)) * dwNumberOfItems   8
  

в противном случае, я предлагаю вам опубликовать исходную собственную структуру данных, возможно, есть гораздо лучшая альтернатива для маршалинга ее из блока памяти.

Комментарии:

1. То есть в массиве нет дополнительной информации, помимо содержащихся в нем фактических элементов?

2. это зависит от маршалируемой собственной структуры, если вы можете маршалировать каждый элемент вручную, я думаю, вы знаете свой stuct. Я не уверен, вам нужно выполнить свои собственные вычисления на основе структуры WLAN_BSS_ENTRY

Ответ №2:

Итак, я понял это, я не знаю, о чем я думал…

 [StructLayout(LayoutKind.Sequential, Pack=1)]
struct WLAN_BSS_LIST
{
    internal uint dwTotalSize;
    internal uint dwNumberOfItems;
    internal WLAN_BSS_ENTRY[] wlanBssEntries;

    internal WLAN_BSS_LIST(IntPtr ppBssList)
    {
        dwTotalSize = (uint)Marshal.ReadInt32(ppBssList);
        dwNumberOfItems = (uint)Marshal.ReadInt32(ppBssList, 4);
        wlanBssEntries = new WLAN_BSS_ENTRY[dwNumberOfItems];
        for (int i = 0; i < dwNumberOfItems; i  )
        {
            IntPtr pWlanBssEntry = new IntPtr(ppBssList.ToInt32()   i * 
                Marshal.SizeOf(typeof(WLAN_BSS_ENTRY))   8);
            wlanBssEntries[i] = (WLAN_BSS_ENTRY)Marshal.
                PtrToStructure(pWlanBssEntry, typeof(WLAN_BSS_ENTRY));
        }
    }
}
  

И

 [StructLayout(LayoutKind.Sequential)]
public struct WLAN_BSS_ENTRY
{
    public DOT11_SSID dot11Ssid;
    public uint uPhyId;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
    public byte[] dot11Bssid;
    public DOT11_BSS_TYPE dot11BssType;
    public DOT11_PHY_TYPE dot11BssPhyType;
    public int lRssi;
    public uint uLinkQuality;
    public bool bInRegDomain;
    public UInt16 usBeaconPeriod;
    public UInt64 ullTimestamp;
    public UInt64 ullHostTimestamp;
    public UInt16 usCapabilityInformation;
    public uint ulChCenterFrequency;
    public WLAN_RATE_SET wlanRateSet;
    public uint ulIeOffset;
    public uint ulIeSize;
}