【发布时间】:2018-04-23 03:16:59
【问题描述】:
我想使用一个在 Python 中返回 AP ssid 列表的 dll 函数,但它需要一个带有 dyamic length array 的预分配结构。不知道怎么定义这样的结构,事先不知道返回的数组长度。
下面是 C# 演示中定义的样子;具体而言,此结构中的 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);
【问题讨论】:
-
这真的取决于 C(不是 C++,更不用说 C#!)库。有些要求您分配内存,有些则需要自己分配。请查阅您的文档,或edit您的问题以链接到它,以便我们查看它的内容。动态结构通常需要由库分配; 猜测某个东西需要多少内存对于生产代码来说是完全不可接受的。
-
我尝试了 create_string_buffer(1024) (我猜这就是分配的意思...),并将返回的值转储为十六进制。我可以看到缓冲区确实包含我所追求的信息。但解析它似乎很困难。如您所见,甚至
itemcount也在这些可变长度数组之间。除了一些示例 C# 代码外,我没有更多文档。它来自 C# SDK。所有细节都已结束。 -
这对我来说就像魔术一样,C# 似乎可以自己计算大小,我不知道在 ctypes 中该做什么。
-
C 知道当您请求静态内存块时该做什么。要处理动态内存,您需要使用
malloc(或一些包装函数;这在某种程度上取决于操作系统)来告诉语言从操作系统请求足够的内存来处理您想要执行的任何任务。 “魔法”可能发生在图书馆内;如果是这样,您只需要确保调用正确的过程以在完成后要求它释放此内存。 -
C# SDK 示例代码似乎分配了一个包含 30 个 SSID 元素的数组,希望这已经足够了。 可能他们这样做是作为一个快速而肮脏的演示,而不是作为最佳实践的真正建议。
标签: python arrays ctypes python-2.5