如何在ctypes中定义具有动态长度数组的结构?

时间:2018-04-23 03:17:00

标签: python arrays ctypes python-2.5

我想使用一个在Python中返回AP ssid列表的dll函数,但它需要一个带有dyamic length array的预分配结构。我不知道如何定义这样的结构,而不事先知道返回的数组长度。

下面是C#demo中定义的样子;具体而言,此结构中的SSID byte array长度会有所不同。

    public extern static bool D300SysUI_WiFiGetAroundSsidStatus(IntPtr SSIDList, int nMaxCount);

    public struct SSIDLISTNET
    {
        public uint ATIMWindow;
        public D300SysUI.NDIS_802_11_AUTHENTICATION_MODE AuthenticationMode;
        public uint BeaconPeriod;
        public uint DSConfig;
        public uint DwellTime;
        public uint HopPattern;
        public uint HopSet;
        public D300SysUI.NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
        public byte[] MacAddress;
        public D300SysUI.NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
        public uint NumberOfItems;
        public uint Privacy;
        public byte[] Reserved;
        public int Rssi;
        public byte[] Ssid;
        public uint SsidLength;
        public byte[] SupportedRates;
    }

估算时我需要create_string_buffer足够长吗?并逐个字节地循环返回缓冲区,并按字母大小将字节分成元素?

如果这是正确的方法,我该如何确定动态数组的结束? (请原谅我的无知,我是ctypes / c ++的新手)

PS:来自C#SDK的示例

        //D300SysUI.SSIDLIST[] items= new D300SysUI.SSIDLIST[30];
        //IntPtr[] ptArray = new IntPtr[1];
        //ptArray[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(D300SysUI.SSIDLIST)) * 30);
        //bool b = D300SysUI.D300SysUI_WiFiGetAroundSsidStatus(ptArray[0], 30);
        //string message = "";
        //string mac = "";
        //if (b)
        //{
        //    items[0] = (D300SysUI.SSIDLIST)Marshal.PtrToStructure((IntPtr)((UInt32)ptArray[0]), typeof(D300SysUI.SSIDLIST));
        //    for (int i =0;i<6;i++)
        //    {
        //        mac += String.Format("{0:X2} ", items[0].MacAddress[i]);
        //    }

        //    message += string.Format("AP:{0},MAC:{1},dBm:{2} \r\n",Encoding.GetEncoding("ASCII").GetString(items[0].Ssid,0,(int)(items[0].SsidLength)),mac,items[0].Rssi);

        //    for (int j = 1; j < items[0].NumberOfItems; j++)
        //    {
        //        items[j] = (D300SysUI.SSIDLIST)Marshal.PtrToStructure((IntPtr)((UInt32)ptArray[0] + j * Marshal.SizeOf(typeof(D300SysUI.SSIDLIST))), typeof(D300SysUI.SSIDLIST));
        //        mac = "";
        //        for (int i = 0; i < 6; i++)
        //        {
        //            mac += String.Format("{0:X2} ", items[j].MacAddress[i]);
        //        }

        //        message += string.Format("AP:{0},MAC:{1},dBm:{2} \r\n", Encoding.GetEncoding("ASCII").GetString(items[j].Ssid, 0, (int)(items[j].SsidLength)), mac, items[j].Rssi);

        //    }
        //}
        //Marshal.FreeHGlobal(ptArray[0]);
        //MessageBox.Show(message);

1 个答案:

答案 0 :(得分:0)

如果您已将SSIDLISTNET定义为cTypes结构,则只需分配所需的数量。如果API将返回的最大值为30,则分配该实例数是一种简单而直接的解决方案。

SSIDlist = SSIDLISTNET * 30

如果你对内存非常有限,你可以将所需的实际项目数量复制到一个只保留那么多的新列表,并del SSIDlist释放你为此列表保留的内存(或者让它超出范围。)