1"""Type classes and a modest collection of standard types.""" 2 3 4from bgenOutput import * 5 6 7class Type: 8 9 """Define the various things you can do with a C type. 10 11 Most methods are intended to be extended or overridden. 12 """ 13 14 def __init__(self, typeName, fmt): 15 """Call with the C name and getargs format for the type. 16 17 Example: int = Type("int", "i") 18 """ 19 self.typeName = typeName 20 self.fmt = fmt 21 22 def declare(self, name, reference=False): 23 """Declare a variable of the type with a given name. 24 25 Example: int.declare('spam') prints "int spam;" 26 """ 27 for decl in self.getArgDeclarations(name, reference): 28 Output("%s;", decl) 29 for decl in self.getAuxDeclarations(name): 30 Output("%s;", decl) 31 32 def getArgDeclarations(self, name, reference=False, constmode=False, outmode=False): 33 """Return the main part of the declarations for this type: the items 34 that will be passed as arguments in the C/C++ function call.""" 35 if reference: 36 ref = "&" 37 else: 38 ref = "" 39 if constmode: 40 const = "const " 41 else: 42 const = "" 43 if outmode: 44 out = "*" 45 else: 46 out = "" 47 return ["%s%s%s%s %s" % (const, self.typeName, ref, out, name)] 48 49 def getAuxDeclarations(self, name): 50 """Return any auxiliary declarations needed for implementing this 51 type, such as helper variables used to hold sizes, etc. These declarations 52 are not part of the C/C++ function call interface.""" 53 return [] 54 55 def getargs(self): 56 return self.getargsFormat(), self.getargsArgs() 57 58 def getargsFormat(self): 59 """Return the format for this type for use with PyArg_Parse(). 60 61 Example: int.getargsFormat() returns the string "i". 62 (getargs is a very old name for PyArg_Parse, hence the name of this method). 63 """ 64 return self.fmt 65 66 def getargsArgs(self, name): 67 """Return an argument for use with PyArg_Parse(). 68 69 Example: int.getargsArgs("spam") returns the string "&spam". 70 """ 71 return "&" + name 72 73 def getargsPreCheck(self, name): 74 """Perform any actions needed before calling getargs(). 75 76 This could include declaring temporary variables and such. 77 """ 78 79 def getargsCheck(self, name): 80 """Perform any needed post-[new]getargs() checks. 81 82 This is type-dependent; the default does not check for errors. 83 An example would be a check for a maximum string length, or it 84 could do post-getargs() copying or conversion.""" 85 86 def passInput(self, name): 87 """Return an argument for passing a variable into a call. 88 89 Example: int.passInput("spam") returns the string "spam". 90 """ 91 return name 92 93 def passOutput(self, name): 94 """Return an argument for returning a variable out of a call. 95 96 Example: int.passOutput("spam") returns the string "&spam". 97 """ 98 return "&" + name 99 100 def passReference(self, name): 101 """Return an argument for C++ pass-by-reference. 102 Default is to call passInput(). 103 """ 104 return self.passInput(name) 105 106 def errorCheck(self, name): 107 """Check for an error returned in the variable. 108 109 This is type-dependent; the default does not check for errors. 110 An example would be a check for a NULL pointer. 111 If an error is found, the generated routine should 112 raise an exception and return NULL. 113 114 XXX There should be a way to add error clean-up code. 115 """ 116 Output("/* XXX no err check for %s %s */", self.typeName, name) 117 118 def mkvalue(self): 119 return self.mkvalueFormat(), self.mkvalueArgs() 120 121 def mkvalueFormat(self): 122 """Return the format for this type for use with Py_BuildValue(). 123 124 This is normally the same as getargsFormat() but it is 125 a separate function to allow future divergence. 126 (mkvalue is a very old name for Py_BuildValue, hence the name of this 127 method). 128 """ 129 return self.getargsFormat() 130 131 def mkvalueArgs(self, name): 132 """Return an argument for use with Py_BuildValue(). 133 134 Example: int.mkvalueArgs("spam") returns the string "spam". 135 """ 136 return name 137 138 def mkvaluePreCheck(self, name): 139 """Perform any actions needed before calling mkvalue(). 140 141 This could include declaring temporary variables and such. 142 """ 143 144 def cleanup(self, name): 145 """Clean up if necessary. 146 147 This is normally empty; it may deallocate buffers etc. 148 """ 149 pass 150 151class ByAddressType(Type): 152 "Simple type that is also passed by address for input" 153 154 def passInput(self, name): 155 return "&%s" % name 156 157 158 159# Sometimes it's useful to define a type that's only usable as input or output parameter 160 161class InputOnlyMixIn: 162 163 "Mix-in class to boobytrap passOutput" 164 165 def passOutput(self, name): 166 raise RuntimeError, "Type '%s' can only be used for input parameters" % self.typeName 167 168class InputOnlyType(InputOnlyMixIn, Type): 169 170 "Same as Type, but only usable for input parameters -- passOutput is boobytrapped" 171 172class OutputOnlyMixIn: 173 174 "Mix-in class to boobytrap passInput" 175 176 def passInput(self, name): 177 raise RuntimeError, "Type '%s' can only be used for output parameters" % self.typeName 178 179class OutputOnlyType(OutputOnlyMixIn, Type): 180 181 "Same as Type, but only usable for output parameters -- passInput is boobytrapped" 182 183 184# A modest collection of standard C types. 185void = None 186char = Type("char", "c") 187short = Type("short", "h") 188unsigned_short = Type("unsigned short", "H") 189int = Type("int", "i") 190long = Type("long", "l") 191unsigned_long = Type("unsigned long", "l") 192float = Type("float", "f") 193double = Type("double", "d") 194 195 196# The most common use of character pointers is a null-terminated string. 197# For input, this is easy. For output, and for other uses of char *, 198# see the module bgenBuffer. 199stringptr = InputOnlyType("char*", "s") 200unicodestringptr = InputOnlyType("wchar_t *", "u") 201 202 203# Some Python related types. 204objectptr = Type("PyObject*", "O") 205stringobjectptr = Type("PyStringObject*", "S") 206# Etc. 207 208 209class FakeType(InputOnlyType): 210 211 """A type that is not represented in the Python version of the interface. 212 213 Instantiate with a value to pass in the call. 214 """ 215 216 def __init__(self, substitute): 217 self.substitute = substitute 218 self.typeName = None # Don't show this argument in __doc__ string 219 220 def getArgDeclarations(self, name, reference=False, constmode=False, outmode=False): 221 return [] 222 223 def getAuxDeclarations(self, name, reference=False): 224 return [] 225 226 def getargsFormat(self): 227 return "" 228 229 def getargsArgs(self, name): 230 return None 231 232 def passInput(self, name): 233 return self.substitute 234 235 236class OpaqueType(Type): 237 238 """A type represented by an opaque object type, always passed by address. 239 240 Instantiate with the type name and the names of the new and convert procs. 241 If fewer than three arguments are passed, the second argument is used 242 to derive the new and convert procs by appending _New and _Convert; it 243 defaults to the first argument. 244 """ 245 246 def __init__(self, name, arg = None, extra = None): 247 self.typeName = name 248 if extra is None: 249 # Two arguments (name, usetype) or one (name) 250 arg = arg or name 251 self.new = arg + '_New' 252 self.convert = arg + '_Convert' 253 else: 254 # Three arguments (name, new, convert) 255 self.new = arg 256 self.convert = extra 257 258 def getargsFormat(self): 259 return "O&" 260 261 def getargsArgs(self, name): 262 return "%s, &%s" % (self.convert, name) 263 264 def passInput(self, name): 265 return "&%s" % name 266 267 def mkvalueFormat(self): 268 return "O&" 269 270 def mkvalueArgs(self, name): 271 return "%s, &%s" % (self.new, name) 272 273 274class OpaqueByValueType(OpaqueType): 275 276 """A type represented by an opaque object type, on input passed BY VALUE. 277 278 Instantiate with the type name, and optionally an object type name whose 279 New/Convert functions will be used. 280 """ 281 282 def passInput(self, name): 283 return name 284 285 def mkvalueArgs(self, name): 286 return "%s, %s" % (self.new, name) 287 288class OpaqueByRefType(OpaqueType): 289 """An opaque object type, passed by reference. 290 291 Instantiate with the type name, and optionally an object type name whose 292 New/Convert functions will be used. 293 """ 294 295 def passInput(self, name): 296 return name 297 298# def passOutput(self, name): 299# return name 300 301 def mkvalueFormat(self): 302 return "O" 303 304 def mkvalueArgs(self, name): 305 return "%s(%s)" % (self.new, name) 306 307class OpaqueByValueStructType(OpaqueByValueType): 308 """Similar to OpaqueByValueType, but we also pass this to mkvalue by 309 address, in stead of by value. 310 """ 311 312 def mkvalueArgs(self, name): 313 return "%s, &%s" % (self.new, name) 314 315 316class OpaqueArrayType(OpaqueByValueType): 317 318 """A type represented by an opaque object type, with ARRAY passing semantics. 319 320 Instantiate with the type name, and optional an object type name whose 321 New/Convert functions will be used. 322 """ 323 324 def getargsArgs(self, name): 325 return "%s, %s" % (self.convert, name) 326 327 def passOutput(self, name): 328 return name 329