I want to use a dll function which returns AP ssid list in Python, But it takes a preallocated struct with dyamic length array inside. I don't know how to define such a structure, without knowing the returned array length in advance.
Below is how the definition looks like in the C# demo; specifically the SSID byte array length in this struct varies.
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;
}
Do I need to create_string_buffer long enough by estimation ? And loop through the returned buffer, byte by byte and assmebly the bytes into element by size?
If that is the right way, how do I determine the end of the dymamic arrays ? (please pardon my ignorance, I am new to ctypes/c++)
PS: Example from the 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);
If you have defined
SSIDLISTNETas a cTypes structure, you just allocate the desired number of these. If the maximum the API will return is 30, allocating that number of instances is a simple and straightforward solution.If you are very constrained on memory, you can probably copy over the required actual number of items to a new list which only holds that many, and
del SSIDlistto free up the memory you reserved for this list (or let it go out of scope).