Я пытаюсь разобраться с ctypes в python, и я могу заставить некоторые простые вещи работать, но когда дело доходит до распаковки 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 и создать класс, который наследуется от ctypes.Structure
, и поэтому я придумал это (я нашел определение структуры hostent
в 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-му индексу после поиска чего-то, что, как я знаю, имеет хотя бы один псевдоним и хотя бы один адрес, я получаю доступ к пустому указателю 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
Любые предложения приветствуются.