问题描述
|
我正在尝试着用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\")
但这给了我hostent
的数据结构。我认为最好的解压缩方法是抓取c struct并创建一个继承自ctypes.Structure
的类,因此我想到了这一点(我在netdb.h
中找到了hostent
struct定义):
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\",(\"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)
,因为null18ѭ用于以空值结尾的字符串。在这种情况下,最好使用“ 19”,如果第一个地址是IPv4地址,则第一个地址应该是“ 20”。