ctypes: return a pointer to a struct

J

Jack

I'm not able to build IP2Location's Python interface so I'm
trying to use ctypes to call its C interface. The functions
return a pointer to the struct below. I haven't been able to
figure out how I should declare the return type of the functions
and read the fields. Any hint is appreciated.

typedef struct
{
char *country_short;
char *country_long;
char *region;
char *city;
char *isp;
float latitude;
float longitude;
char *domain;
char *zipcode;
char *timezone;
char *netspeed;
} IP2LocationRecord;
 
S

sturlamolden

typedef struct
{
char *country_short;
char *country_long;
char *region;
char *city;
char *isp;
float latitude;
float longitude;
char *domain;
char *zipcode;
char *timezone;
char *netspeed;

} IP2LocationRecord;


First define a struct type IP2LocationRecord by subclassing from
ctypes.Structure. Then define a pointer type as
ctypes.POINTER(IP2LocationRecord) and set that as the function's
restype attribute. See the ctypes tutorial or reference for details.
 
S

sturlamolden

First define a struct type IP2LocationRecord by subclassing from
ctypes.Structure. Then define a pointer type as
ctypes.POINTER(IP2LocationRecord) and set that as the function's
restype attribute. See the ctypes tutorial or reference for details.

Which is to say:

import ctypes

class IP2LocationRecord(ctypes.Structure):
_fields_ = [
('country_short', ctypes.c_char_p),
('country_long', ctypes.c_char_p),
('region', ctypes.c_char_p),
('city', ctypes.c_char_p),
('isp', ctypes.c_char_p),
('latitude', ctypes.c_float),
('longitude', ctypes.c_float),
('domain', ctypes.c_char_p),
('zipcode', ctypes.c_char_p),
('timezone', ctypes.c_char_p),
('netspeed', ctypes.c_char_p),
]

IP2LocationRecord_Ptr_t = ctypes.POINTER(IP2LocationRecord)

function.restype = IP2LocationRecord_Ptr_t
 
J

Jack

Thanks for the prompt and detailed reply. I tried that but was getting this
error:

AttributeError: 'LP_IP2LocationRecord' object has no attribute
'country_short'

Here's my version, which I think is equivalent to yours:
(as a matter of fact, I also tried yours and got the same error.)

class IP2LocationRecord(Structure):
_fields_ = [("country_short", c_char_p),
("country_long", c_char_p),
("region", c_char_p),
("city", c_char_p),
("isp", c_char_p),
("latitude", c_float),
("longitude", c_float),
("domain", c_char_p),
("zipcode", c_char_p),
("timezone", c_char_p),
("netspeed", c_char_p)]

IP2Location_get_all.restype = POINTER(IP2LocationRecord)
IP2LocationObj = IP2Location_open(thisdir + '/IP-COUNTRY-SAMPLE.BIN')
rec = IP2Location_get_all(IP2LocationObj, '64.233.167.99')
print rec.country_short
IP2Location_close(IP2LocationObj)


sturlamolden said:
First define a struct type IP2LocationRecord by subclassing from
ctypes.Structure. Then define a pointer type as
ctypes.POINTER(IP2LocationRecord) and set that as the function's
restype attribute. See the ctypes tutorial or reference for details.

Which is to say:

import ctypes

class IP2LocationRecord(ctypes.Structure):
_fields_ = [
('country_short', ctypes.c_char_p),
('country_long', ctypes.c_char_p),
('region', ctypes.c_char_p),
('city', ctypes.c_char_p),
('isp', ctypes.c_char_p),
('latitude', ctypes.c_float),
('longitude', ctypes.c_float),
('domain', ctypes.c_char_p),
('zipcode', ctypes.c_char_p),
('timezone', ctypes.c_char_p),
('netspeed', ctypes.c_char_p),
]

IP2LocationRecord_Ptr_t = ctypes.POINTER(IP2LocationRecord)

function.restype = IP2LocationRecord_Ptr_t
 
S

sturlamolden

AttributeError: 'LP_IP2LocationRecord' object has no attribute
'country_short'

As it says, LP_IP2LocationRecord has no attribute called
'country_short'. IP2LocationRecord does.

Use the 'contents' attribute to dereference the pointer. That is:

yourstruct.contents.country_short
 
J

Jack

That worked. Thank you!
As it says, LP_IP2LocationRecord has no attribute called
'country_short'. IP2LocationRecord does.

Use the 'contents' attribute to dereference the pointer. That is:

yourstruct.contents.country_short
 
S

sturlamolden

IP2Location_get_all.restype = POINTER(IP2LocationRecord)
IP2LocationObj = IP2Location_open(thisdir + '/IP-COUNTRY-SAMPLE.BIN')
rec = IP2Location_get_all(IP2LocationObj, '64.233.167.99')
print rec.country_short

print rec.contents.country_short
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,480
Members
44,900
Latest member
Nell636132

Latest Threads

Top