我试图让我了解python中的ctypes,并且能够使一些简单的事情起作用,但是当涉及到解压缩c结构时,我发现自己遇到了一些困难.我决定要学习这一点,应该花一点时间,虽然我知道套接字标准库实现了gethostbyname_ex(),但我想我会尝试使用ctypes和libc.gethostbyname()来实现它.
我能够很容易地执行libc.gethostbyname():
#!/usr/bin/env python
from ctypes import *
cdll.LoadLibrary('libc.so.6')
libc = CDLL('libc.so.6')
he = libc.gethostbyname("www.google.com")
但这给了我一个重要的数据结构.我认为最好的解压缩方法是获取c结构并创建一个从ctypes.Structure继承的类,因此我想到了这一点(我在netdb.h中找到了托管结构定义):
class hostent(Structure):
'''
struct hostent
{
char *h_name; /* Official name of host. */
char **h_aliases; /* Alias list. */
int h_addrtype; /* Host address type. */
int h_length; /* Length of address. */
char **h_addr_list; /* List of addresses from name server. */
}
'''
_fields_ = [("h_name", c_char_p), ("h_aliases", POINTER(c_char_p)),
("h_addrtype", c_int), ("h_length", c_int),
("h_addr_list", POINTER(c_char_p))]
我不清楚的地方是我是否正确设置了h_aliases和h_addr_list字段,因为每当我尝试将它们作为数组访问时,甚至在查找我知道的东西之后至少在第0个索引处都具有一个别名并且至少一个地址,我得到一个NULL指针访问ValueError异常:
>>> he = hostent(libc.gethostbyname("www.google.com"))
>>> pprint.pprint(he.h_addr_list)
<__main__.LP_c_char_p object at 0xb75dae84>
>>> print he.h_addr_list[0]
Traceback (most recent call last):
File "/tmp/py2659JxK", line 24, in <module>
print he.h_addr_list[0]
ValueError: NULL pointer access
欢迎大家提出意见.
解决方法:
您需要定义gethostbyname的返回类型是:
>>> libc.gethostbyname.restype = POINTER(hostent)
>>> he = libc.gethostbyname("www.google.com")[0]
>>> he.h_aliases[0]
'www.google.com'
另外,h_addr_list不应声明为POINTER(c_char_p),因为c_char_p用于以空值结尾的字符串.在这种情况下,POINTER(POINTER(c_ubyte))会更好,如果它是IPv4地址,则第一个地址将是he.h_addr_list [0] [:4].
标签:structure,ctypes,python 来源: https://codeday.me/bug/20191102/1992100.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。