Thomas Wouters | 0e3f591 | 2006-08-11 14:57:12 +0000 | [diff] [blame] | 1 | /***************************************************************** |
| 2 | This file should be kept compatible with Python 2.3, see PEP 291. |
| 3 | *****************************************************************/ |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 4 | |
Thomas Wouters | a977329 | 2006-04-21 09:43:23 +0000 | [diff] [blame] | 5 | #if (PY_VERSION_HEX < 0x02050000) |
| 6 | typedef int Py_ssize_t; |
Thomas Wouters | a977329 | 2006-04-21 09:43:23 +0000 | [diff] [blame] | 7 | #endif |
| 8 | |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 9 | #ifndef MS_WIN32 |
| 10 | #define max(a, b) ((a) > (b) ? (a) : (b)) |
| 11 | #define min(a, b) ((a) < (b) ? (a) : (b)) |
| 12 | |
| 13 | #define PARAMFLAG_FIN 0x1 |
| 14 | #define PARAMFLAG_FOUT 0x2 |
| 15 | #define PARAMFLAG_FLCID 0x4 |
| 16 | #endif |
| 17 | |
| 18 | /* |
| 19 | Backwards compatibility: |
| 20 | Python2.2 used LONG_LONG instead of PY_LONG_LONG |
| 21 | */ |
| 22 | #if defined(HAVE_LONG_LONG) && !defined(PY_LONG_LONG) |
| 23 | #define PY_LONG_LONG LONG_LONG |
| 24 | #endif |
| 25 | |
Guido van Rossum | 360e4b8 | 2007-05-14 22:51:27 +0000 | [diff] [blame] | 26 | #if SIZEOF_VOID_P == SIZEOF_LONG |
| 27 | #define PY_VOID_P_CODE "k" |
| 28 | #elif defined(HAVE_LONG_LONG) && (SIZEOF_VOID_P == SIZEOF_LONG_LONG) |
| 29 | #define PY_VOID_P_CODE "K" |
| 30 | #endif |
| 31 | |
Thomas Wouters | 00ee7ba | 2006-08-21 19:07:27 +0000 | [diff] [blame] | 32 | typedef struct tagPyCArgObject PyCArgObject; |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 33 | typedef struct tagCDataObject CDataObject; |
Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 34 | typedef PyObject *(* GETFUNC)(void *, unsigned size); |
| 35 | typedef PyObject *(* SETFUNC)(void *, PyObject *value, unsigned size); |
Thomas Wouters | 00ee7ba | 2006-08-21 19:07:27 +0000 | [diff] [blame] | 36 | typedef PyCArgObject *(* PARAMFUNC)(CDataObject *obj); |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 37 | |
| 38 | /* A default buffer in CDataObject, which can be used for small C types. If |
| 39 | this buffer is too small, PyMem_Malloc will be called to create a larger one, |
| 40 | and this one is not used. |
| 41 | |
| 42 | Making CDataObject a variable size object would be a better solution, but more |
| 43 | difficult in the presence of CFuncPtrObject. Maybe later. |
| 44 | */ |
| 45 | union value { |
| 46 | char c[16]; |
| 47 | short s; |
| 48 | int i; |
| 49 | long l; |
| 50 | float f; |
| 51 | double d; |
| 52 | #ifdef HAVE_LONG_LONG |
| 53 | PY_LONG_LONG ll; |
| 54 | #endif |
| 55 | }; |
| 56 | |
| 57 | /* |
| 58 | Hm. Are there CDataObject's which do not need the b_objects member? In |
| 59 | this case we probably should introduce b_flags to mark it as present... If |
| 60 | b_objects is not present/unused b_length is unneeded as well. |
| 61 | */ |
| 62 | |
| 63 | struct tagCDataObject { |
| 64 | PyObject_HEAD |
| 65 | char *b_ptr; /* pointer to memory block */ |
| 66 | int b_needsfree; /* need _we_ free the memory? */ |
| 67 | CDataObject *b_base; /* pointer to base object or NULL */ |
Thomas Heller | fe8f862 | 2006-03-14 19:53:09 +0000 | [diff] [blame] | 68 | Py_ssize_t b_size; /* size of memory block in bytes */ |
| 69 | Py_ssize_t b_length; /* number of references we need */ |
| 70 | Py_ssize_t b_index; /* index of this object into base's |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 71 | b_object list */ |
Thomas Wouters | 0e3f591 | 2006-08-11 14:57:12 +0000 | [diff] [blame] | 72 | PyObject *b_objects; /* dictionary of references we need to keep, or Py_None */ |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 73 | union value b_value; |
| 74 | }; |
| 75 | |
| 76 | typedef struct { |
Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 77 | ffi_closure *pcl; /* the C callable */ |
| 78 | ffi_cif cif; |
| 79 | PyObject *converters; |
| 80 | PyObject *callable; |
| 81 | SETFUNC setfunc; |
| 82 | ffi_type *restype; |
| 83 | ffi_type *atypes[0]; |
| 84 | } ffi_info; |
| 85 | |
| 86 | typedef struct { |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 87 | /* First part identical to tagCDataObject */ |
| 88 | PyObject_HEAD |
| 89 | char *b_ptr; /* pointer to memory block */ |
| 90 | int b_needsfree; /* need _we_ free the memory? */ |
| 91 | CDataObject *b_base; /* pointer to base object or NULL */ |
Thomas Heller | fe8f862 | 2006-03-14 19:53:09 +0000 | [diff] [blame] | 92 | Py_ssize_t b_size; /* size of memory block in bytes */ |
| 93 | Py_ssize_t b_length; /* number of references we need */ |
| 94 | Py_ssize_t b_index; /* index of this object into base's |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 95 | b_object list */ |
| 96 | PyObject *b_objects; /* list of references we need to keep */ |
| 97 | union value b_value; |
| 98 | /* end of tagCDataObject, additional fields follow */ |
| 99 | |
Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 100 | ffi_info *thunk; |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 101 | PyObject *callable; |
| 102 | |
| 103 | /* These two fields will override the ones in the type's stgdict if |
| 104 | they are set */ |
| 105 | PyObject *converters; |
| 106 | PyObject *argtypes; |
| 107 | PyObject *restype; |
| 108 | PyObject *checker; |
| 109 | PyObject *errcheck; |
| 110 | #ifdef MS_WIN32 |
| 111 | int index; |
| 112 | GUID *iid; |
| 113 | #endif |
| 114 | PyObject *paramflags; |
| 115 | } CFuncPtrObject; |
| 116 | |
| 117 | extern PyTypeObject StgDict_Type; |
| 118 | #define StgDict_CheckExact(v) ((v)->ob_type == &StgDict_Type) |
| 119 | #define StgDict_Check(v) PyObject_TypeCheck(v, &StgDict_Type) |
| 120 | |
| 121 | extern int StructUnionType_update_stgdict(PyObject *fields, PyObject *type, int isStruct); |
Thomas Heller | fe8f862 | 2006-03-14 19:53:09 +0000 | [diff] [blame] | 122 | extern int PyType_stginfo(PyTypeObject *self, Py_ssize_t *psize, Py_ssize_t *palign, Py_ssize_t *plength); |
| 123 | extern int PyObject_stginfo(PyObject *self, Py_ssize_t *psize, Py_ssize_t *palign, Py_ssize_t *plength); |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 124 | |
| 125 | |
| 126 | |
| 127 | extern PyTypeObject CData_Type; |
| 128 | #define CDataObject_CheckExact(v) ((v)->ob_type == &CData_Type) |
| 129 | #define CDataObject_Check(v) PyObject_TypeCheck(v, &CData_Type) |
| 130 | |
| 131 | extern PyTypeObject SimpleType_Type; |
| 132 | #define SimpleTypeObject_CheckExact(v) ((v)->ob_type == &SimpleType_Type) |
| 133 | #define SimpleTypeObject_Check(v) PyObject_TypeCheck(v, &SimpleType_Type) |
| 134 | |
| 135 | extern PyTypeObject CField_Type; |
| 136 | extern struct fielddesc *getentry(char *fmt); |
| 137 | |
| 138 | |
| 139 | extern PyObject * |
| 140 | CField_FromDesc(PyObject *desc, int index, |
| 141 | int *pfield_size, int bitsize, int *pbitofs, |
| 142 | int *psize, int *poffset, int *palign, |
| 143 | int pack, int is_big_endian); |
| 144 | |
| 145 | extern PyObject *CData_AtAddress(PyObject *type, void *buf); |
Thomas Heller | fe8f862 | 2006-03-14 19:53:09 +0000 | [diff] [blame] | 146 | extern PyObject *CData_FromBytes(PyObject *type, char *data, Py_ssize_t length); |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 147 | |
| 148 | extern PyTypeObject ArrayType_Type; |
| 149 | extern PyTypeObject Array_Type; |
| 150 | extern PyTypeObject PointerType_Type; |
| 151 | extern PyTypeObject Pointer_Type; |
| 152 | extern PyTypeObject CFuncPtr_Type; |
| 153 | extern PyTypeObject CFuncPtrType_Type; |
| 154 | extern PyTypeObject StructType_Type; |
| 155 | |
| 156 | #define ArrayTypeObject_Check(v) PyObject_TypeCheck(v, &ArrayType_Type) |
| 157 | #define ArrayObject_Check(v) PyObject_TypeCheck(v, &Array_Type) |
| 158 | #define PointerObject_Check(v) PyObject_TypeCheck(v, &Pointer_Type) |
| 159 | #define PointerTypeObject_Check(v) PyObject_TypeCheck(v, &PointerType_Type) |
| 160 | #define CFuncPtrObject_Check(v) PyObject_TypeCheck(v, &CFuncPtr_Type) |
| 161 | #define CFuncPtrTypeObject_Check(v) PyObject_TypeCheck(v, &CFuncPtrType_Type) |
| 162 | #define StructTypeObject_Check(v) PyObject_TypeCheck(v, &StructType_Type) |
| 163 | |
| 164 | extern PyObject * |
Thomas Heller | fe8f862 | 2006-03-14 19:53:09 +0000 | [diff] [blame] | 165 | CreateArrayType(PyObject *itemtype, Py_ssize_t length); |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 166 | |
| 167 | extern void init_callbacks_in_module(PyObject *m); |
| 168 | |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 169 | extern PyMethodDef module_methods[]; |
| 170 | |
Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 171 | extern ffi_info *AllocFunctionCallback(PyObject *callable, |
| 172 | PyObject *converters, |
| 173 | PyObject *restype, |
| 174 | int stdcall); |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 175 | /* a table entry describing a predefined ctypes type */ |
| 176 | struct fielddesc { |
| 177 | char code; |
| 178 | SETFUNC setfunc; |
| 179 | GETFUNC getfunc; |
| 180 | ffi_type *pffi_type; /* always statically allocated */ |
| 181 | SETFUNC setfunc_swapped; |
| 182 | GETFUNC getfunc_swapped; |
| 183 | }; |
| 184 | |
| 185 | typedef struct { |
| 186 | PyObject_HEAD |
Thomas Heller | fe8f862 | 2006-03-14 19:53:09 +0000 | [diff] [blame] | 187 | Py_ssize_t offset; |
| 188 | Py_ssize_t size; |
| 189 | Py_ssize_t index; /* Index into CDataObject's |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 190 | object array */ |
| 191 | PyObject *proto; /* a type or NULL */ |
| 192 | GETFUNC getfunc; /* getter function if proto is NULL */ |
| 193 | SETFUNC setfunc; /* setter function if proto is NULL */ |
Thomas Wouters | 0e3f591 | 2006-08-11 14:57:12 +0000 | [diff] [blame] | 194 | int anonymous; |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 195 | } CFieldObject; |
| 196 | |
| 197 | /* A subclass of PyDictObject, used as the instance dictionary of ctypes |
| 198 | metatypes */ |
| 199 | typedef struct { |
| 200 | PyDictObject dict; /* first part identical to PyDictObject */ |
| 201 | /* The size and align fields are unneeded, they are in ffi_type as well. As |
| 202 | an experiment shows, it's trivial to get rid of them, the only thing to |
| 203 | remember is that in ArrayType_new the ffi_type fields must be filled in - |
| 204 | so far it was unneeded because libffi doesn't support arrays at all |
| 205 | (because they are passed as pointers to function calls anyway). But it's |
| 206 | too much risk to change that now, and there are other fields which doen't |
| 207 | belong into this structure anyway. Maybe in ctypes 2.0... (ctypes 2000?) |
| 208 | */ |
Thomas Heller | fe8f862 | 2006-03-14 19:53:09 +0000 | [diff] [blame] | 209 | Py_ssize_t size; /* number of bytes */ |
| 210 | Py_ssize_t align; /* alignment requirements */ |
| 211 | Py_ssize_t length; /* number of fields */ |
Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 212 | ffi_type ffi_type_pointer; |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 213 | PyObject *proto; /* Only for Pointer/ArrayObject */ |
| 214 | SETFUNC setfunc; /* Only for simple objects */ |
| 215 | GETFUNC getfunc; /* Only for simple objects */ |
Thomas Wouters | 00ee7ba | 2006-08-21 19:07:27 +0000 | [diff] [blame] | 216 | PARAMFUNC paramfunc; |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 217 | |
| 218 | /* Following fields only used by CFuncPtrType_Type instances */ |
| 219 | PyObject *argtypes; /* tuple of CDataObjects */ |
| 220 | PyObject *converters; /* tuple([t.from_param for t in argtypes]) */ |
| 221 | PyObject *restype; /* CDataObject or NULL */ |
| 222 | PyObject *checker; |
| 223 | int flags; /* calling convention and such */ |
| 224 | } StgDictObject; |
| 225 | |
| 226 | /**************************************************************** |
| 227 | StgDictObject fields |
| 228 | |
| 229 | setfunc and getfunc is only set for simple data types, it is copied from the |
| 230 | corresponding fielddesc entry. These are functions to set and get the value |
| 231 | in a memory block. |
| 232 | They should probably by used by other types as well. |
| 233 | |
| 234 | proto is only used for Pointer and Array types - it points to the item type |
| 235 | object. |
| 236 | |
| 237 | Probably all the magic ctypes methods (like from_param) should have C |
| 238 | callable wrappers in the StgDictObject. For simple data type, for example, |
| 239 | the fielddesc table could have entries for C codec from_param functions or |
| 240 | other methods as well, if a subtype overrides this method in Python at |
| 241 | construction time, or assigns to it later, tp_setattro should update the |
| 242 | StgDictObject function to a generic one. |
| 243 | |
| 244 | Currently, CFuncPtr types have 'converters' and 'checker' entries in their |
| 245 | type dict. They are only used to cache attributes from other entries, whihc |
| 246 | is wrong. |
| 247 | |
| 248 | One use case is the .value attribute that all simple types have. But some |
| 249 | complex structures, like VARIANT, represent a single value also, and should |
| 250 | have this attribute. |
| 251 | |
| 252 | Another use case is a _check_retval_ function, which is called when a ctypes |
| 253 | type is used as return type of a function to validate and compute the return |
| 254 | value. |
| 255 | |
| 256 | Common ctypes protocol: |
| 257 | |
| 258 | - setfunc: store a python value in a memory block |
| 259 | - getfunc: convert data from a memory block into a python value |
| 260 | |
| 261 | - checkfunc: validate and convert a return value from a function call |
| 262 | - toparamfunc: convert a python value into a function argument |
| 263 | |
| 264 | *****************************************************************/ |
| 265 | |
| 266 | /* May return NULL, but does not set an exception! */ |
| 267 | extern StgDictObject *PyType_stgdict(PyObject *obj); |
| 268 | |
| 269 | /* May return NULL, but does not set an exception! */ |
| 270 | extern StgDictObject *PyObject_stgdict(PyObject *self); |
| 271 | |
| 272 | extern int StgDict_clone(StgDictObject *src, StgDictObject *dst); |
| 273 | |
| 274 | typedef int(* PPROC)(void); |
| 275 | |
| 276 | PyObject *_CallProc(PPROC pProc, |
| 277 | PyObject *arguments, |
| 278 | #ifdef MS_WIN32 |
| 279 | IUnknown *pIUnk, |
| 280 | GUID *iid, |
| 281 | #endif |
| 282 | int flags, |
| 283 | PyObject *argtypes, |
| 284 | PyObject *restype, |
| 285 | PyObject *checker); |
| 286 | |
| 287 | |
| 288 | #define FUNCFLAG_STDCALL 0x0 |
| 289 | #define FUNCFLAG_CDECL 0x1 |
| 290 | #define FUNCFLAG_HRESULT 0x2 |
| 291 | #define FUNCFLAG_PYTHONAPI 0x4 |
| 292 | |
| 293 | #define DICTFLAG_FINAL 0x1000 |
| 294 | |
Thomas Wouters | 00ee7ba | 2006-08-21 19:07:27 +0000 | [diff] [blame] | 295 | struct tagPyCArgObject { |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 296 | PyObject_HEAD |
| 297 | ffi_type *pffi_type; |
| 298 | char tag; |
| 299 | union { |
| 300 | char c; |
| 301 | char b; |
| 302 | short h; |
| 303 | int i; |
| 304 | long l; |
| 305 | #ifdef HAVE_LONG_LONG |
| 306 | PY_LONG_LONG q; |
| 307 | #endif |
| 308 | double d; |
| 309 | float f; |
| 310 | void *p; |
| 311 | } value; |
| 312 | PyObject *obj; |
| 313 | int size; /* for the 'V' tag */ |
Thomas Wouters | 00ee7ba | 2006-08-21 19:07:27 +0000 | [diff] [blame] | 314 | }; |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 315 | |
| 316 | extern PyTypeObject PyCArg_Type; |
| 317 | extern PyCArgObject *new_CArgObject(void); |
| 318 | #define PyCArg_CheckExact(v) ((v)->ob_type == &PyCArg_Type) |
| 319 | extern PyCArgObject *new_CArgObject(void); |
| 320 | |
| 321 | extern PyObject * |
| 322 | CData_get(PyObject *type, GETFUNC getfunc, PyObject *src, |
Thomas Heller | fe8f862 | 2006-03-14 19:53:09 +0000 | [diff] [blame] | 323 | Py_ssize_t index, Py_ssize_t size, char *ptr); |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 324 | |
| 325 | extern int |
| 326 | CData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, |
Thomas Heller | fe8f862 | 2006-03-14 19:53:09 +0000 | [diff] [blame] | 327 | Py_ssize_t index, Py_ssize_t size, char *ptr); |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 328 | |
| 329 | extern void Extend_Error_Info(PyObject *exc_class, char *fmt, ...); |
| 330 | |
| 331 | struct basespec { |
| 332 | CDataObject *base; |
Thomas Heller | fe8f862 | 2006-03-14 19:53:09 +0000 | [diff] [blame] | 333 | Py_ssize_t index; |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 334 | char *adr; |
| 335 | }; |
| 336 | |
| 337 | extern char basespec_string[]; |
| 338 | |
| 339 | extern ffi_type *GetType(PyObject *obj); |
| 340 | |
| 341 | /* exception classes */ |
| 342 | extern PyObject *PyExc_ArgError; |
| 343 | |
| 344 | extern char *conversion_mode_encoding; |
| 345 | extern char *conversion_mode_errors; |
| 346 | |
| 347 | /* Python 2.4 macros, which are not available in Python 2.3 */ |
| 348 | |
| 349 | #ifndef Py_CLEAR |
| 350 | #define Py_CLEAR(op) \ |
| 351 | do { \ |
| 352 | if (op) { \ |
| 353 | PyObject *tmp = (PyObject *)(op); \ |
| 354 | (op) = NULL; \ |
| 355 | Py_DECREF(tmp); \ |
| 356 | } \ |
| 357 | } while (0) |
| 358 | #endif |
| 359 | |
| 360 | #ifndef Py_VISIT |
| 361 | /* Utility macro to help write tp_traverse functions. |
| 362 | * To use this macro, the tp_traverse function must name its arguments |
| 363 | * "visit" and "arg". This is intended to keep tp_traverse functions |
| 364 | * looking as much alike as possible. |
| 365 | */ |
| 366 | #define Py_VISIT(op) \ |
| 367 | do { \ |
| 368 | if (op) { \ |
| 369 | int vret = visit((op), arg); \ |
| 370 | if (vret) \ |
| 371 | return vret; \ |
| 372 | } \ |
| 373 | } while (0) |
| 374 | #endif |
| 375 | |
| 376 | /* Python's PyUnicode_*WideChar functions are broken ... */ |
| 377 | #if defined(Py_USING_UNICODE) && defined(HAVE_WCHAR_H) |
| 378 | # define CTYPES_UNICODE |
| 379 | #endif |
| 380 | |
| 381 | |
| 382 | #ifdef CTYPES_UNICODE |
| 383 | # undef PyUnicode_FromWideChar |
| 384 | # define PyUnicode_FromWideChar My_PyUnicode_FromWideChar |
| 385 | |
| 386 | # undef PyUnicode_AsWideChar |
| 387 | # define PyUnicode_AsWideChar My_PyUnicode_AsWideChar |
| 388 | |
Thomas Wouters | 0e3f591 | 2006-08-11 14:57:12 +0000 | [diff] [blame] | 389 | extern PyObject *My_PyUnicode_FromWideChar(const wchar_t *, Py_ssize_t); |
| 390 | extern int My_PyUnicode_AsWideChar(PyUnicodeObject *, wchar_t *, Py_ssize_t); |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 391 | |
| 392 | #endif |
| 393 | |
| 394 | extern void FreeClosure(void *); |
| 395 | extern void *MallocClosure(void); |
| 396 | |
| 397 | extern void _AddTraceback(char *, char *, int); |
| 398 | |
Thomas Heller | fe8f862 | 2006-03-14 19:53:09 +0000 | [diff] [blame] | 399 | extern PyObject *CData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr); |
Thomas Heller | d4c9320 | 2006-03-08 19:35:11 +0000 | [diff] [blame] | 400 | |
| 401 | /* XXX better name needed! */ |
| 402 | extern int IsSimpleSubType(PyObject *obj); |
| 403 | |
| 404 | |
| 405 | #ifdef MS_WIN32 |
| 406 | extern PyObject *ComError; |
| 407 | #endif |
| 408 | |
| 409 | /* |
| 410 | Local Variables: |
| 411 | compile-command: "python setup.py -q build install --home ~" |
| 412 | End: |
| 413 | */ |