Re: [ctypes-users] Extending a ctype to put into a structure
Brought to you by:
theller
From: Thomas H. <th...@py...> - 2005-01-12 18:10:31
|
Guillaume Proux <gui...@sc...> writes: > Hi, > > I wanted to do the following thing: Create a subclass of c_int that > could be used to transparently get a formatted string from the integer > when accessing the value property. However it does not work as > expected if used from a structure. > > > class usdollars(c_int): > def valueget(self): > intval=super(usdollars,self).value > return self._format(intval) > def valueset(self,newvalue): > setattr(super(usdollars,self),'value',newvalue) > value=property(valueget,valueset) > def _format(self,value): > s='%03d'%value > decpart=s[-2:] > if int(decpart)==0: > decpart='' > else: > decpart='.'+decpart > integerpart=s[:-2] > parts=[] > while len(integerpart)>3: > parts.append(integerpart[-3:]) > integerpart=integerpart[:-3] > parts.append(integerpart) > parts.reverse() > return '$'+','.join(parts)+decpart def > __repr__(self): > return "usdollars(%s)"%self.valueget() > > > Then I use it with > >>> a=usdollars(100000) > >>> a.value > '$1,000' > > but if i do: > >>> class test(Structure): > ... _fields_ = [ ('money',usdollars) ] > ... > >>> b=test() > >>> b.money=100000 > >>> b.money > 100000 > > And not '$1,000' as I hoped. > also assigning the attribute value does not work as hoped > >>> a.value=1000 > Traceback (most recent call last): > File "<stdin>", line 1, in ? > File "<stdin>", line 6, in valueset > TypeError: 'super' object has only read-only attributes (assign to .value) > > > How do ctypes Structure implement its properties? The primitive data types like c_int have some internal behaviour that cannot be overridden. This is needed so that getting a structure field declared as c_int, for example, returns an integer instead of a c_int instance. Same for setting its value. > It is not a big issue because easy to workaround. It would be > fantastic though to inherit from ctypes native types! You can define custom datatypes, compatible with C, as structures. Like this (not exactly what you described above, but maybe also useful, and you will get the idea): The dollars type stores the value in pennies. Thomas <code> from ctypes import Structure, c_int class dollars(Structure): _fields_ = [("_value", c_int)] def _get(self): return "%.2f $" % (self._value / 100.) def _set(self, value): val, d = value.split() assert d == "$" self._value = int(float(val) * 100) value = property(_get, _set) class MyStruct(Structure): _fields_ = [("money", dollars)] m = MyStruct() print m.money.value m.money.value = "1.23 $" print m.money.value </code> |