working with ctypes and complex data structures

Michael Felt michael at felt.demon.nl
Thu Oct 6 06:15:07 EDT 2016



On 04-Oct-16 04:48, eryk sun wrote:
> On Mon, Oct 3, 2016 at 9:27 PM, Michael Felt <michael at felt.demon.nl> wrote:
>> int perfstat_subsystem_total(
>>     perfstat_id_t *name,
>>     perfstat_subsystem_total_t *userbuff,
>>     int sizeof_struct,
>>     int desired_number);
>> ...
>>     +79  class cpu_total:
>>     +80      def __init__(self):
>>     +81          __perfstat__ = CDLL("libperfstat.a(shr_64.o)")
Thanks for the model below - a lot to think about. Some was expected, 
some is a gift!
Python is "a lot to learn". This helps a great deal.
> Move loading the library and defining function prototypes to either
> the module or class body. Also, don't use dunder names. The convention
> for a private attribute is a single underscore. For type safety,
> define each function's argtypes (and restype where required, the
> default is c_int). For a more Pythonic interface, define a ctypes
> errcheck function that encapsulates raising an appropriate exception
> when a C call fails. For example:
>
>      import ctypes
>
>      # If the following types are used generally, define them at
>      # the module level, else define them in the class namespace
>      # that uses them.
>
>      perfstat = ctypes.CDLL("libperfstat.a(shr_64.o)")
>
>      class perfstat_id_t(ctypes.Structure):
>          pass
>
>      IDENTIFIER_LENGTH = 64
>
>      class time64_t(ctypes._SimpleCData):
>          _type_ = ctypes.c_int64._type_
>
>      time_t = time64_t
>
>      class perfstat_cpu_total_t(ctypes.Structure):
>          _fields_ = (("ncpus",       ctypes.c_int),
>                      ("ncpus_cfg",   ctypes.c_int),
>                      ("description", ctypes.c_char * IDENTIFIER_LENGTH),
>                      ("buffer1",     ctypes.c_ulonglong * 15),
>                      ("lbolt",       time_t),
>                      ("loadavg",     ctypes.c_ulonglong * 3),
>                      ("buffer2",     ctypes.c_ulonglong * 29),
>                      ("ncpus_high",  ctypes.c_int),
>                      ("puser",       ctypes.c_ulonglong),
>                      ("psys",        ctypes.c_ulonglong),
>                      ("pidle",       ctypes.c_ulonglong),
>                      ("pwait",       ctypes.c_ulonglong),
>                      ("buffer3",     ctypes.c_ulonglong * 12))
>
>      def _perfstat_errcheck(result, func, args):
>          if result == -1:
>              # get error info and
>              raise SomeException()
>          return args
>
>      class CPUTotal(object):
>          # These may be defined here or just referenced here.
>          _perfstat = perfstat
>          _perfstat_id_t = perfstat_id_t
>          _perfstat_cpu_total_t = perfstat_cpu_total_t
>
>          _cpu_total = _perfstat.perfstat_cpu_total
>          _cpu_total.errcheck = _perfstat_errcheck
>          _cpu_total.argtypes = (
>              ctypes.POINTER(_perfstat_id_t),
>              ctypes.POINTER(_perfstat_cpu_total_t),
>              ctypes.c_int, ctypes.c_int)
>
>          def __init__(self):
>              self._tcpu = self._perfstat_cpu_total_t()
>              self._cpu_total(None,
>                              ctypes.byref(self._tcpu),
>                              ctypes.sizeof(self._tcpu), 1)




More information about the Python-list mailing list