解码ctypes结构

问题描述

| 我正在尝试着用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”。