Welcome, guest | Sign In | My Account | Store | Cart

Like my earlier C function decorator, this recipe is designed to make it easier to interact with C by removing some of the boilerplate code from defining C structs in Python.

Python, 57 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import ctypes

class C_struct:
	"""Decorator to convert the given class into a C struct."""

	# contains a dict of all known translatable types
	types = ctypes.__dict__

	@classmethod
	def register_type(cls, typename, obj):
		"""Adds the new class to the dict of understood types."""
		cls.types[typename] = obj

	def __call__(self, cls):
		"""Converts the given class into a C struct.
		
		Usage:
			>>> @C_struct()
			... class Account:
			... 	first_name = "c_char_p"
			...	last_name = "c_char_p"
			... 	balance = "c_float"
			...
			>>> a = Account()
			>>> a
			<cstruct.Account object at 0xb7c0ee84>

		A very important note: while it *is* possible to
		instantiate these classes as follows:

			>>> a = Account("Geremy", "Condra", 0.42)

		This is strongly discouraged, because there is at
		present no way to ensure what order the field names
		will be read in.
		"""
		
		# build the field mapping (names -> types)
		fields = []
		for k, v in vars(cls).items():
			# don't wrap private variables
			if not k.startswith("_"):
				# if its a pointer
				if v.startswith("*"):
					field_type = ctypes.POINTER(self.types[v[1:]])
				else:
					field_type = self.types[v]
				new_field = (k, field_type)
				fields.append(new_field)

		# make our bases tuple
		bases = (ctypes.Structure,) + tuple((base for base in cls.__bases__)) 
		# finish up our wrapping dict
		class_attrs = {"_fields_": fields, "__doc__": cls.__doc__}

		# now create our class
		return type(cls.__name__, bases, class_attrs)	

3 comments

Jiri Zahradil 14 years, 11 months ago  # | flag

Line 12 seems to be wrong, it is meant to be:

cls.types[typename] = obj
geremy condra (author) 14 years, 11 months ago  # | flag

You're correct, of course- I'll correct it immediately. And thanks for the feedback!

Anand 14 years, 10 months ago  # | flag

How about an example ?

Created by geremy condra on Wed, 29 Apr 2009 (MIT)
Python recipes (4591)
geremy condra's recipes (8)

Required Modules

Other Information and Tasks