blob: c4f73ba451928598ac490f4902ed57abdf0fbecd [file] [log] [blame]
Thomas Hellerc2da9942006-06-12 20:56:48 +00001/*****************************************************************
2 This file should be kept compatible with Python 2.3, see PEP 291.
3 *****************************************************************/
4
5
Thomas Hellerd4c93202006-03-08 19:35:11 +00006/*
7 ToDo:
8
Thomas Heller5c6af802009-04-24 20:31:47 +00009 Get rid of the checker (and also the converters) field in PyCFuncPtrObject and
Thomas Hellerd4c93202006-03-08 19:35:11 +000010 StgDictObject, and replace them by slot functions in StgDictObject.
11
12 think about a buffer-like object (memory? bytes?)
13
14 Should POINTER(c_char) and POINTER(c_wchar) have a .value property?
15 What about c_char and c_wchar arrays then?
16
17 Add from_mmap, from_file, from_string metaclass methods.
18
19 Maybe we can get away with from_file (calls read) and with a from_buffer
20 method?
21
22 And what about the to_mmap, to_file, to_str(?) methods? They would clobber
23 the namespace, probably. So, functions instead? And we already have memmove...
24*/
25
26/*
27
28Name methods, members, getsets
29==============================================================================
30
Thomas Heller5c6af802009-04-24 20:31:47 +000031PyCStructType_Type __new__(), from_address(), __mul__(), from_param()
Thomas Hellerd4c93202006-03-08 19:35:11 +000032UnionType_Type __new__(), from_address(), __mul__(), from_param()
Thomas Heller5c6af802009-04-24 20:31:47 +000033PyCPointerType_Type __new__(), from_address(), __mul__(), from_param(), set_type()
34PyCArrayType_Type __new__(), from_address(), __mul__(), from_param()
35PyCSimpleType_Type __new__(), from_address(), __mul__(), from_param()
Thomas Hellerd4c93202006-03-08 19:35:11 +000036
Thomas Heller5c6af802009-04-24 20:31:47 +000037PyCData_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +000038 Struct_Type __new__(), __init__()
Thomas Heller5c6af802009-04-24 20:31:47 +000039 PyCPointer_Type __new__(), __init__(), _as_parameter_, contents
40 PyCArray_Type __new__(), __init__(), _as_parameter_, __get/setitem__(), __len__()
Thomas Hellerd4c93202006-03-08 19:35:11 +000041 Simple_Type __new__(), __init__(), _as_parameter_
42
Thomas Heller5c6af802009-04-24 20:31:47 +000043PyCField_Type
44PyCStgDict_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +000045
46==============================================================================
47
48class methods
49-------------
50
51It has some similarity to the byref() construct compared to pointer()
52from_address(addr)
53 - construct an instance from a given memory block (sharing this memory block)
54
55from_param(obj)
56 - typecheck and convert a Python object into a C function call parameter
57 the result may be an instance of the type, or an integer or tuple
58 (typecode, value[, obj])
59
60instance methods/properties
61---------------------------
62
63_as_parameter_
64 - convert self into a C function call parameter
65 This is either an integer, or a 3-tuple (typecode, value, obj)
66
67functions
68---------
69
70sizeof(cdata)
71 - return the number of bytes the buffer contains
72
73sizeof(ctype)
74 - return the number of bytes the buffer of an instance would contain
75
76byref(cdata)
77
78addressof(cdata)
79
80pointer(cdata)
81
82POINTER(ctype)
83
84bytes(cdata)
85 - return the buffer contents as a sequence of bytes (which is currently a string)
86
87*/
88
89/*
Thomas Heller5c6af802009-04-24 20:31:47 +000090 * PyCStgDict_Type
91 * PyCStructType_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +000092 * UnionType_Type
Thomas Heller5c6af802009-04-24 20:31:47 +000093 * PyCPointerType_Type
94 * PyCArrayType_Type
95 * PyCSimpleType_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +000096 *
Thomas Heller5c6af802009-04-24 20:31:47 +000097 * PyCData_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +000098 * Struct_Type
99 * Union_Type
Thomas Heller5c6af802009-04-24 20:31:47 +0000100 * PyCArray_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +0000101 * Simple_Type
Thomas Heller5c6af802009-04-24 20:31:47 +0000102 * PyCPointer_Type
103 * PyCField_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +0000104 *
105 */
106
Thomas Hellerfffd9392008-03-25 21:18:39 +0000107#define PY_SSIZE_T_CLEAN
108
Thomas Hellerd4c93202006-03-08 19:35:11 +0000109#include "Python.h"
110#include "structmember.h"
111
112#include <ffi.h>
113#ifdef MS_WIN32
114#include <windows.h>
Thomas Heller59feb6f2006-03-22 12:59:53 +0000115#include <malloc.h>
116#ifndef IS_INTRESOURCE
117#define IS_INTRESOURCE(x) (((size_t)(x) >> 16) == 0)
118#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +0000119# ifdef _WIN32_WCE
120/* Unlike desktop Windows, WinCE has both W and A variants of
121 GetProcAddress, but the default W version is not what we want */
122# undef GetProcAddress
123# define GetProcAddress GetProcAddressA
124# endif
125#else
126#include "ctypes_dlfcn.h"
127#endif
128#include "ctypes.h"
129
130PyObject *PyExc_ArgError;
Thomas Heller046e6a42008-04-14 16:10:07 +0000131
132/* This dict maps ctypes types to POINTER types */
Thomas Heller5c6af802009-04-24 20:31:47 +0000133PyObject *_ctypes_ptrtype_cache;
Thomas Heller046e6a42008-04-14 16:10:07 +0000134
Thomas Hellerd4c93202006-03-08 19:35:11 +0000135static PyTypeObject Simple_Type;
136
Thomas Hellera06a1a82008-02-13 20:21:53 +0000137/* a callable object used for unpickling */
138static PyObject *_unpickle;
139
Thomas Heller5c6af802009-04-24 20:31:47 +0000140char *_ctypes_conversion_encoding = NULL;
141char *_ctypes_conversion_errors = NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000142
143
Thomas Hellere4c03e42008-01-24 18:36:27 +0000144/****************************************************************/
145
Thomas Heller8e8ba152008-04-04 08:35:44 +0000146#if (PY_VERSION_HEX < 0x02040000)
147/* Only in Python 2.4 and up */
148static PyObject *
149PyTuple_Pack(int n, ...)
150{
151 int i;
152 PyObject *o;
153 PyObject *result;
154 PyObject **items;
155 va_list vargs;
156
157 va_start(vargs, n);
158 result = PyTuple_New(n);
159 if (result == NULL)
160 return NULL;
161 items = ((PyTupleObject *)result)->ob_item;
162 for (i = 0; i < n; i++) {
163 o = va_arg(vargs, PyObject *);
164 Py_INCREF(o);
165 items[i] = o;
166 }
167 va_end(vargs);
168 return result;
169}
170#endif
171
172/****************************************************************/
173
Thomas Hellere4c03e42008-01-24 18:36:27 +0000174typedef struct {
175 PyObject_HEAD
176 PyObject *key;
177 PyObject *dict;
178} DictRemoverObject;
179
180static void
181_DictRemover_dealloc(PyObject *_self)
182{
183 DictRemoverObject *self = (DictRemoverObject *)_self;
184 Py_XDECREF(self->key);
185 Py_XDECREF(self->dict);
186 Py_TYPE(self)->tp_free(_self);
187}
188
189static PyObject *
190_DictRemover_call(PyObject *_self, PyObject *args, PyObject *kw)
191{
192 DictRemoverObject *self = (DictRemoverObject *)_self;
193 if (self->key && self->dict) {
194 if (-1 == PyDict_DelItem(self->dict, self->key))
195 /* XXX Error context */
196 PyErr_WriteUnraisable(Py_None);
197 Py_DECREF(self->key);
198 self->key = NULL;
199 Py_DECREF(self->dict);
200 self->dict = NULL;
201 }
202 Py_INCREF(Py_None);
203 return Py_None;
204}
205
206static PyTypeObject DictRemover_Type = {
207 PyVarObject_HEAD_INIT(NULL, 0)
208 "_ctypes.DictRemover", /* tp_name */
209 sizeof(DictRemoverObject), /* tp_basicsize */
210 0, /* tp_itemsize */
211 _DictRemover_dealloc, /* tp_dealloc */
212 0, /* tp_print */
213 0, /* tp_getattr */
214 0, /* tp_setattr */
215 0, /* tp_compare */
216 0, /* tp_repr */
217 0, /* tp_as_number */
218 0, /* tp_as_sequence */
219 0, /* tp_as_mapping */
220 0, /* tp_hash */
221 _DictRemover_call, /* tp_call */
222 0, /* tp_str */
223 0, /* tp_getattro */
224 0, /* tp_setattro */
225 0, /* tp_as_buffer */
226/* XXX should participate in GC? */
227 Py_TPFLAGS_DEFAULT, /* tp_flags */
228 "deletes a key from a dictionary", /* tp_doc */
229 0, /* tp_traverse */
230 0, /* tp_clear */
231 0, /* tp_richcompare */
232 0, /* tp_weaklistoffset */
233 0, /* tp_iter */
234 0, /* tp_iternext */
235 0, /* tp_methods */
236 0, /* tp_members */
237 0, /* tp_getset */
238 0, /* tp_base */
239 0, /* tp_dict */
240 0, /* tp_descr_get */
241 0, /* tp_descr_set */
242 0, /* tp_dictoffset */
243 0, /* tp_init */
244 0, /* tp_alloc */
Thomas Heller41e22ff2008-03-14 21:06:21 +0000245 0, /* tp_new */
Thomas Hellere4c03e42008-01-24 18:36:27 +0000246 0, /* tp_free */
247};
248
249int
250PyDict_SetItemProxy(PyObject *dict, PyObject *key, PyObject *item)
251{
252 PyObject *obj;
253 DictRemoverObject *remover;
254 PyObject *proxy;
255 int result;
256
257 obj = PyObject_CallObject((PyObject *)&DictRemover_Type, NULL);
258 if (obj == NULL)
259 return -1;
260
261 remover = (DictRemoverObject *)obj;
262 assert(remover->key == NULL);
263 assert(remover->dict == NULL);
264 Py_INCREF(key);
265 remover->key = key;
266 Py_INCREF(dict);
267 remover->dict = dict;
268
269 proxy = PyWeakref_NewProxy(item, obj);
270 Py_DECREF(obj);
271 if (proxy == NULL)
272 return -1;
273
274 result = PyDict_SetItem(dict, key, proxy);
275 Py_DECREF(proxy);
276 return result;
277}
278
279PyObject *
280PyDict_GetItemProxy(PyObject *dict, PyObject *key)
281{
282 PyObject *result;
283 PyObject *item = PyDict_GetItem(dict, key);
284
285 if (item == NULL)
286 return NULL;
287 if (!PyWeakref_CheckProxy(item))
288 return item;
289 result = PyWeakref_GET_OBJECT(item);
290 if (result == Py_None)
291 return NULL;
292 return result;
293}
294
Thomas Hellerd4c93202006-03-08 19:35:11 +0000295/******************************************************************/
296/*
Thomas Heller2e75c452008-06-05 17:51:15 +0000297 Allocate a memory block for a pep3118 format string, copy prefix (if
298 non-null) and suffix into it. Returns NULL on failure, with the error
299 indicator set. If called with a suffix of NULL the error indicator must
300 already be set.
301 */
302char *
Thomas Heller5c6af802009-04-24 20:31:47 +0000303_ctypes_alloc_format_string(const char *prefix, const char *suffix)
Thomas Heller2e75c452008-06-05 17:51:15 +0000304{
305 size_t len;
306 char *result;
307
308 if (suffix == NULL) {
309 assert(PyErr_Occurred());
310 return NULL;
311 }
312 len = strlen(suffix);
313 if (prefix)
314 len += strlen(prefix);
315 result = PyMem_Malloc(len + 1);
316 if (result == NULL)
317 return NULL;
318 if (prefix)
319 strcpy(result, prefix);
320 else
321 result[0] = '\0';
322 strcat(result, suffix);
323 return result;
324}
325
326/*
Thomas Heller5c6af802009-04-24 20:31:47 +0000327 PyCStructType_Type - a meta type/class. Creating a new class using this one as
Thomas Hellerd4c93202006-03-08 19:35:11 +0000328 __metaclass__ will call the contructor StructUnionType_new. It replaces the
329 tp_dict member with a new instance of StgDict, and initializes the C
330 accessible fields somehow.
331*/
332
Thomas Heller86720042006-08-14 11:17:48 +0000333static PyCArgObject *
334StructUnionType_paramfunc(CDataObject *self)
335{
336 PyCArgObject *parg;
337 StgDictObject *stgdict;
338
Thomas Heller5c6af802009-04-24 20:31:47 +0000339 parg = PyCArgObject_new();
Thomas Heller86720042006-08-14 11:17:48 +0000340 if (parg == NULL)
341 return NULL;
342
343 parg->tag = 'V';
344 stgdict = PyObject_stgdict((PyObject *)self);
Thomas Hellerd32e6162006-08-16 13:03:11 +0000345 assert(stgdict); /* Cannot be NULL for structure/union instances */
Thomas Heller86720042006-08-14 11:17:48 +0000346 parg->pffi_type = &stgdict->ffi_type_pointer;
347 /* For structure parameters (by value), parg->value doesn't contain the structure
348 data itself, instead parg->value.p *points* to the structure's data
349 See also _ctypes.c, function _call_function_pointer().
350 */
351 parg->value.p = self->b_ptr;
352 parg->size = self->b_size;
353 Py_INCREF(self);
354 parg->obj = (PyObject *)self;
355 return parg;
356}
357
Thomas Hellerd4c93202006-03-08 19:35:11 +0000358static PyObject *
359StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isStruct)
360{
361 PyTypeObject *result;
362 PyObject *fields;
363 StgDictObject *dict;
364
365 /* create the new instance (which is a class,
366 since we are a metatype!) */
367 result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
368 if (!result)
369 return NULL;
370
371 /* keep this for bw compatibility */
372 if (PyDict_GetItemString(result->tp_dict, "_abstract_"))
373 return (PyObject *)result;
374
Thomas Heller5c6af802009-04-24 20:31:47 +0000375 dict = (StgDictObject *)PyObject_CallObject((PyObject *)&PyCStgDict_Type, NULL);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000376 if (!dict) {
377 Py_DECREF(result);
378 return NULL;
379 }
380 /* replace the class dict by our updated stgdict, which holds info
381 about storage requirements of the instances */
382 if (-1 == PyDict_Update((PyObject *)dict, result->tp_dict)) {
383 Py_DECREF(result);
384 Py_DECREF((PyObject *)dict);
385 return NULL;
386 }
387 Py_DECREF(result->tp_dict);
388 result->tp_dict = (PyObject *)dict;
Thomas Heller5c6af802009-04-24 20:31:47 +0000389 dict->format = _ctypes_alloc_format_string(NULL, "B");
Thomas Hellerc0b2a802008-07-15 17:03:08 +0000390 if (dict->format == NULL) {
391 Py_DECREF(result);
392 return NULL;
393 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000394
Thomas Heller86720042006-08-14 11:17:48 +0000395 dict->paramfunc = StructUnionType_paramfunc;
396
Thomas Hellerd4c93202006-03-08 19:35:11 +0000397 fields = PyDict_GetItemString((PyObject *)dict, "_fields_");
398 if (!fields) {
399 StgDictObject *basedict = PyType_stgdict((PyObject *)result->tp_base);
400
401 if (basedict == NULL)
402 return (PyObject *)result;
403 /* copy base dict */
Thomas Heller5c6af802009-04-24 20:31:47 +0000404 if (-1 == PyCStgDict_clone(dict, basedict)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +0000405 Py_DECREF(result);
406 return NULL;
407 }
408 dict->flags &= ~DICTFLAG_FINAL; /* clear the 'final' flag in the subclass dict */
409 basedict->flags |= DICTFLAG_FINAL; /* set the 'final' flag in the baseclass dict */
410 return (PyObject *)result;
411 }
412
413 if (-1 == PyObject_SetAttrString((PyObject *)result, "_fields_", fields)) {
414 Py_DECREF(result);
415 return NULL;
416 }
417 return (PyObject *)result;
418}
419
420static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +0000421PyCStructType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000422{
423 return StructUnionType_new(type, args, kwds, 1);
424}
425
426static PyObject *
427UnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
428{
429 return StructUnionType_new(type, args, kwds, 0);
430}
431
432static char from_address_doc[] =
433"C.from_address(integer) -> C instance\naccess a C instance at the specified address";
434
435static PyObject *
436CDataType_from_address(PyObject *type, PyObject *value)
437{
438 void *buf;
439 if (!PyInt_Check(value) && !PyLong_Check(value)) {
440 PyErr_SetString(PyExc_TypeError,
441 "integer expected");
442 return NULL;
443 }
444 buf = (void *)PyLong_AsVoidPtr(value);
445 if (PyErr_Occurred())
446 return NULL;
Thomas Heller5c6af802009-04-24 20:31:47 +0000447 return PyCData_AtAddress(type, buf);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000448}
449
Thomas Heller6ad5fbb2008-04-25 15:44:16 +0000450static char from_buffer_doc[] =
451"C.from_buffer(object, offset=0) -> C instance\ncreate a C instance from a writeable buffer";
452
453static int
454KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep);
455
456static PyObject *
457CDataType_from_buffer(PyObject *type, PyObject *args)
458{
459 void *buffer;
460 Py_ssize_t buffer_len;
461 Py_ssize_t offset = 0;
462 PyObject *obj, *result;
463 StgDictObject *dict = PyType_stgdict(type);
464 assert (dict);
465
466 if (!PyArg_ParseTuple(args,
467#if (PY_VERSION_HEX < 0x02050000)
468 "O|i:from_buffer",
469#else
470 "O|n:from_buffer",
471#endif
472 &obj, &offset))
473 return NULL;
474
475 if (-1 == PyObject_AsWriteBuffer(obj, &buffer, &buffer_len))
476 return NULL;
477
478 if (offset < 0) {
479 PyErr_SetString(PyExc_ValueError,
Mark Dickinsoncf4ad762009-05-20 17:55:31 +0000480 "offset cannot be negative");
Thomas Heller6ad5fbb2008-04-25 15:44:16 +0000481 return NULL;
482 }
483 if (dict->size > buffer_len - offset) {
484 PyErr_Format(PyExc_ValueError,
485#if (PY_VERSION_HEX < 0x02050000)
486 "Buffer size too small (%d instead of at least %d bytes)",
487#else
488 "Buffer size too small (%zd instead of at least %zd bytes)",
489#endif
490 buffer_len, dict->size + offset);
491 return NULL;
492 }
493
Thomas Heller5c6af802009-04-24 20:31:47 +0000494 result = PyCData_AtAddress(type, (char *)buffer + offset);
Thomas Heller6ad5fbb2008-04-25 15:44:16 +0000495 if (result == NULL)
496 return NULL;
497
498 Py_INCREF(obj);
499 if (-1 == KeepRef((CDataObject *)result, -1, obj)) {
500 Py_DECREF(result);
501 return NULL;
502 }
503 return result;
504}
505
506static char from_buffer_copy_doc[] =
507"C.from_buffer_copy(object, offset=0) -> C instance\ncreate a C instance from a readable buffer";
508
509static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +0000510GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
Thomas Heller6ad5fbb2008-04-25 15:44:16 +0000511
512static PyObject *
513CDataType_from_buffer_copy(PyObject *type, PyObject *args)
514{
Thomas Hellera52b2442008-05-29 19:18:12 +0000515 const void *buffer;
Thomas Heller6ad5fbb2008-04-25 15:44:16 +0000516 Py_ssize_t buffer_len;
517 Py_ssize_t offset = 0;
518 PyObject *obj, *result;
519 StgDictObject *dict = PyType_stgdict(type);
520 assert (dict);
521
522 if (!PyArg_ParseTuple(args,
523#if (PY_VERSION_HEX < 0x02050000)
524 "O|i:from_buffer",
525#else
526 "O|n:from_buffer",
527#endif
528 &obj, &offset))
529 return NULL;
530
531 if (-1 == PyObject_AsReadBuffer(obj, &buffer, &buffer_len))
532 return NULL;
533
534 if (offset < 0) {
535 PyErr_SetString(PyExc_ValueError,
Mark Dickinsoncf4ad762009-05-20 17:55:31 +0000536 "offset cannot be negative");
Thomas Heller6ad5fbb2008-04-25 15:44:16 +0000537 return NULL;
538 }
539
540 if (dict->size > buffer_len - offset) {
541 PyErr_Format(PyExc_ValueError,
542#if (PY_VERSION_HEX < 0x02050000)
543 "Buffer size too small (%d instead of at least %d bytes)",
544#else
545 "Buffer size too small (%zd instead of at least %zd bytes)",
546#endif
547 buffer_len, dict->size + offset);
548 return NULL;
549 }
550
Thomas Heller5c6af802009-04-24 20:31:47 +0000551 result = GenericPyCData_new((PyTypeObject *)type, NULL, NULL);
Thomas Heller6ad5fbb2008-04-25 15:44:16 +0000552 if (result == NULL)
553 return NULL;
554 memcpy(((CDataObject *)result)->b_ptr,
555 (char *)buffer+offset, dict->size);
556 return result;
557}
558
Thomas Hellerd4c93202006-03-08 19:35:11 +0000559static char in_dll_doc[] =
560"C.in_dll(dll, name) -> C instance\naccess a C instance in a dll";
561
562static PyObject *
563CDataType_in_dll(PyObject *type, PyObject *args)
564{
565 PyObject *dll;
566 char *name;
567 PyObject *obj;
568 void *handle;
569 void *address;
570
571 if (!PyArg_ParseTuple(args, "Os:in_dll", &dll, &name))
572 return NULL;
573
574 obj = PyObject_GetAttrString(dll, "_handle");
575 if (!obj)
576 return NULL;
577 if (!PyInt_Check(obj) && !PyLong_Check(obj)) {
578 PyErr_SetString(PyExc_TypeError,
579 "the _handle attribute of the second argument must be an integer");
580 Py_DECREF(obj);
581 return NULL;
582 }
583 handle = (void *)PyLong_AsVoidPtr(obj);
584 Py_DECREF(obj);
585 if (PyErr_Occurred()) {
586 PyErr_SetString(PyExc_ValueError,
587 "could not convert the _handle attribute to a pointer");
588 return NULL;
589 }
590
591#ifdef MS_WIN32
592 address = (void *)GetProcAddress(handle, name);
593 if (!address) {
594 PyErr_Format(PyExc_ValueError,
595 "symbol '%s' not found",
596 name);
597 return NULL;
598 }
599#else
600 address = (void *)ctypes_dlsym(handle, name);
601 if (!address) {
Thomas Hellerd4c93202006-03-08 19:35:11 +0000602#ifdef __CYGWIN__
603/* dlerror() isn't very helpful on cygwin */
Georg Brandl2c079292009-02-13 11:10:04 +0000604 PyErr_Format(PyExc_ValueError,
Thomas Hellerd4c93202006-03-08 19:35:11 +0000605 "symbol '%s' not found (%s) ",
Georg Brandl2c079292009-02-13 11:10:04 +0000606 name);
607#else
608 PyErr_SetString(PyExc_ValueError, ctypes_dlerror());
Thomas Hellerd4c93202006-03-08 19:35:11 +0000609#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +0000610 return NULL;
611 }
612#endif
Thomas Heller5c6af802009-04-24 20:31:47 +0000613 return PyCData_AtAddress(type, address);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000614}
615
616static char from_param_doc[] =
617"Convert a Python object into a function call parameter.";
618
619static PyObject *
620CDataType_from_param(PyObject *type, PyObject *value)
621{
Thomas Heller86720042006-08-14 11:17:48 +0000622 PyObject *as_parameter;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000623 if (1 == PyObject_IsInstance(value, type)) {
624 Py_INCREF(value);
625 return value;
626 }
627 if (PyCArg_CheckExact(value)) {
628 PyCArgObject *p = (PyCArgObject *)value;
629 PyObject *ob = p->obj;
Thomas Heller4c9dfc82006-03-16 19:26:21 +0000630 const char *ob_name;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000631 StgDictObject *dict;
632 dict = PyType_stgdict(type);
633
634 /* If we got a PyCArgObject, we must check if the object packed in it
635 is an instance of the type's dict->proto */
Thomas Hellerd4c93202006-03-08 19:35:11 +0000636 if(dict && ob
637 && PyObject_IsInstance(ob, dict->proto)) {
638 Py_INCREF(value);
639 return value;
640 }
Christian Heimese93237d2007-12-19 02:37:44 +0000641 ob_name = (ob) ? Py_TYPE(ob)->tp_name : "???";
Thomas Hellerd4c93202006-03-08 19:35:11 +0000642 PyErr_Format(PyExc_TypeError,
643 "expected %s instance instead of pointer to %s",
Thomas Heller4c9dfc82006-03-16 19:26:21 +0000644 ((PyTypeObject *)type)->tp_name, ob_name);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000645 return NULL;
646 }
Thomas Heller86720042006-08-14 11:17:48 +0000647
648 as_parameter = PyObject_GetAttrString(value, "_as_parameter_");
649 if (as_parameter) {
650 value = CDataType_from_param(type, as_parameter);
651 Py_DECREF(as_parameter);
652 return value;
653 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000654 PyErr_Format(PyExc_TypeError,
655 "expected %s instance instead of %s",
656 ((PyTypeObject *)type)->tp_name,
Christian Heimese93237d2007-12-19 02:37:44 +0000657 Py_TYPE(value)->tp_name);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000658 return NULL;
659}
660
661static PyMethodDef CDataType_methods[] = {
662 { "from_param", CDataType_from_param, METH_O, from_param_doc },
663 { "from_address", CDataType_from_address, METH_O, from_address_doc },
Thomas Heller6ad5fbb2008-04-25 15:44:16 +0000664 { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, },
665 { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, },
Thomas Hellerd4c93202006-03-08 19:35:11 +0000666 { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc },
667 { NULL, NULL },
668};
669
670static PyObject *
Thomas Hellerfe8f8622006-03-14 19:53:09 +0000671CDataType_repeat(PyObject *self, Py_ssize_t length)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000672{
Thomas Heller45f59ab2006-06-10 19:51:46 +0000673 if (length < 0)
674 return PyErr_Format(PyExc_ValueError,
675#if (PY_VERSION_HEX < 0x02050000)
676 "Array length must be >= 0, not %d",
677#else
678 "Array length must be >= 0, not %zd",
679#endif
680 length);
Thomas Heller5c6af802009-04-24 20:31:47 +0000681 return PyCArrayType_from_ctype(self, length);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000682}
683
684static PySequenceMethods CDataType_as_sequence = {
685 0, /* inquiry sq_length; */
686 0, /* binaryfunc sq_concat; */
687 CDataType_repeat, /* intargfunc sq_repeat; */
688 0, /* intargfunc sq_item; */
689 0, /* intintargfunc sq_slice; */
690 0, /* intobjargproc sq_ass_item; */
691 0, /* intintobjargproc sq_ass_slice; */
692 0, /* objobjproc sq_contains; */
693
694 0, /* binaryfunc sq_inplace_concat; */
695 0, /* intargfunc sq_inplace_repeat; */
696};
697
698static int
699CDataType_clear(PyTypeObject *self)
700{
701 StgDictObject *dict = PyType_stgdict((PyObject *)self);
702 if (dict)
703 Py_CLEAR(dict->proto);
704 return PyType_Type.tp_clear((PyObject *)self);
705}
706
707static int
708CDataType_traverse(PyTypeObject *self, visitproc visit, void *arg)
709{
710 StgDictObject *dict = PyType_stgdict((PyObject *)self);
711 if (dict)
712 Py_VISIT(dict->proto);
713 return PyType_Type.tp_traverse((PyObject *)self, visit, arg);
714}
715
716static int
Thomas Heller5c6af802009-04-24 20:31:47 +0000717PyCStructType_setattro(PyObject *self, PyObject *key, PyObject *value)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000718{
719 /* XXX Should we disallow deleting _fields_? */
Amaury Forgeot d'Arc7cdf5f52008-01-14 01:07:27 +0000720 if (-1 == PyType_Type.tp_setattro(self, key, value))
Thomas Hellerd4c93202006-03-08 19:35:11 +0000721 return -1;
722
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000723 if (value && PyString_Check(key) &&
724 0 == strcmp(PyString_AS_STRING(key), "_fields_"))
Thomas Heller5c6af802009-04-24 20:31:47 +0000725 return PyCStructUnionType_update_stgdict(self, value, 1);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000726 return 0;
727}
728
729
730static int
731UnionType_setattro(PyObject *self, PyObject *key, PyObject *value)
732{
733 /* XXX Should we disallow deleting _fields_? */
734 if (-1 == PyObject_GenericSetAttr(self, key, value))
735 return -1;
736
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000737 if (PyString_Check(key) &&
738 0 == strcmp(PyString_AS_STRING(key), "_fields_"))
Thomas Heller5c6af802009-04-24 20:31:47 +0000739 return PyCStructUnionType_update_stgdict(self, value, 0);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000740 return 0;
741}
742
743
Thomas Heller5c6af802009-04-24 20:31:47 +0000744PyTypeObject PyCStructType_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000745 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Heller5c6af802009-04-24 20:31:47 +0000746 "_ctypes.PyCStructType", /* tp_name */
Thomas Hellerd4c93202006-03-08 19:35:11 +0000747 0, /* tp_basicsize */
748 0, /* tp_itemsize */
749 0, /* tp_dealloc */
750 0, /* tp_print */
751 0, /* tp_getattr */
752 0, /* tp_setattr */
753 0, /* tp_compare */
754 0, /* tp_repr */
755 0, /* tp_as_number */
756 &CDataType_as_sequence, /* tp_as_sequence */
757 0, /* tp_as_mapping */
758 0, /* tp_hash */
759 0, /* tp_call */
760 0, /* tp_str */
761 0, /* tp_getattro */
Thomas Heller5c6af802009-04-24 20:31:47 +0000762 PyCStructType_setattro, /* tp_setattro */
Thomas Hellerd4c93202006-03-08 19:35:11 +0000763 0, /* tp_as_buffer */
764 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
765 "metatype for the CData Objects", /* tp_doc */
766 (traverseproc)CDataType_traverse, /* tp_traverse */
767 (inquiry)CDataType_clear, /* tp_clear */
768 0, /* tp_richcompare */
769 0, /* tp_weaklistoffset */
770 0, /* tp_iter */
771 0, /* tp_iternext */
772 CDataType_methods, /* tp_methods */
773 0, /* tp_members */
774 0, /* tp_getset */
775 0, /* tp_base */
776 0, /* tp_dict */
777 0, /* tp_descr_get */
778 0, /* tp_descr_set */
779 0, /* tp_dictoffset */
780 0, /* tp_init */
781 0, /* tp_alloc */
Thomas Heller5c6af802009-04-24 20:31:47 +0000782 PyCStructType_new, /* tp_new */
Thomas Hellerd4c93202006-03-08 19:35:11 +0000783 0, /* tp_free */
784};
785
786static PyTypeObject UnionType_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000787 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000788 "_ctypes.UnionType", /* tp_name */
789 0, /* tp_basicsize */
790 0, /* tp_itemsize */
791 0, /* tp_dealloc */
792 0, /* tp_print */
793 0, /* tp_getattr */
794 0, /* tp_setattr */
795 0, /* tp_compare */
796 0, /* tp_repr */
797 0, /* tp_as_number */
798 &CDataType_as_sequence, /* tp_as_sequence */
799 0, /* tp_as_mapping */
800 0, /* tp_hash */
801 0, /* tp_call */
802 0, /* tp_str */
803 0, /* tp_getattro */
804 UnionType_setattro, /* tp_setattro */
805 0, /* tp_as_buffer */
806 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
807 "metatype for the CData Objects", /* tp_doc */
808 (traverseproc)CDataType_traverse, /* tp_traverse */
809 (inquiry)CDataType_clear, /* tp_clear */
810 0, /* tp_richcompare */
811 0, /* tp_weaklistoffset */
812 0, /* tp_iter */
813 0, /* tp_iternext */
814 CDataType_methods, /* tp_methods */
815 0, /* tp_members */
816 0, /* tp_getset */
817 0, /* tp_base */
818 0, /* tp_dict */
819 0, /* tp_descr_get */
820 0, /* tp_descr_set */
821 0, /* tp_dictoffset */
822 0, /* tp_init */
823 0, /* tp_alloc */
824 UnionType_new, /* tp_new */
825 0, /* tp_free */
826};
827
828
829/******************************************************************/
830
831/*
832
Thomas Heller5c6af802009-04-24 20:31:47 +0000833The PyCPointerType_Type metaclass must ensure that the subclass of Pointer can be
Thomas Hellerd4c93202006-03-08 19:35:11 +0000834created. It must check for a _type_ attribute in the class. Since are no
835runtime created properties, a CField is probably *not* needed ?
836
837class IntPointer(Pointer):
838 _type_ = "i"
839
Thomas Heller5c6af802009-04-24 20:31:47 +0000840The PyCPointer_Type provides the functionality: a contents method/property, a
Thomas Hellerd4c93202006-03-08 19:35:11 +0000841size property/method, and the sequence protocol.
842
843*/
844
845static int
Thomas Heller5c6af802009-04-24 20:31:47 +0000846PyCPointerType_SetProto(StgDictObject *stgdict, PyObject *proto)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000847{
Thomas Heller4c9dfc82006-03-16 19:26:21 +0000848 if (!proto || !PyType_Check(proto)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +0000849 PyErr_SetString(PyExc_TypeError,
850 "_type_ must be a type");
851 return -1;
852 }
Thomas Heller4c9dfc82006-03-16 19:26:21 +0000853 if (!PyType_stgdict(proto)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +0000854 PyErr_SetString(PyExc_TypeError,
855 "_type_ must have storage info");
856 return -1;
857 }
858 Py_INCREF(proto);
859 Py_XDECREF(stgdict->proto);
860 stgdict->proto = proto;
861 return 0;
862}
863
Thomas Heller86720042006-08-14 11:17:48 +0000864static PyCArgObject *
Thomas Heller5c6af802009-04-24 20:31:47 +0000865PyCPointerType_paramfunc(CDataObject *self)
Thomas Heller86720042006-08-14 11:17:48 +0000866{
867 PyCArgObject *parg;
868
Thomas Heller5c6af802009-04-24 20:31:47 +0000869 parg = PyCArgObject_new();
Thomas Heller86720042006-08-14 11:17:48 +0000870 if (parg == NULL)
871 return NULL;
872
873 parg->tag = 'P';
874 parg->pffi_type = &ffi_type_pointer;
875 Py_INCREF(self);
876 parg->obj = (PyObject *)self;
877 parg->value.p = *(void **)self->b_ptr;
878 return parg;
879}
880
Thomas Hellerd4c93202006-03-08 19:35:11 +0000881static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +0000882PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000883{
884 PyTypeObject *result;
885 StgDictObject *stgdict;
886 PyObject *proto;
887 PyObject *typedict;
888
889 typedict = PyTuple_GetItem(args, 2);
890 if (!typedict)
891 return NULL;
892/*
893 stgdict items size, align, length contain info about pointers itself,
894 stgdict->proto has info about the pointed to type!
895*/
896 stgdict = (StgDictObject *)PyObject_CallObject(
Thomas Heller5c6af802009-04-24 20:31:47 +0000897 (PyObject *)&PyCStgDict_Type, NULL);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000898 if (!stgdict)
899 return NULL;
900 stgdict->size = sizeof(void *);
Thomas Heller5c6af802009-04-24 20:31:47 +0000901 stgdict->align = _ctypes_get_fielddesc("P")->pffi_type->alignment;
Thomas Heller55d031e2006-04-12 19:07:36 +0000902 stgdict->length = 1;
Skip Montanaro058be9a2006-04-18 19:45:17 +0000903 stgdict->ffi_type_pointer = ffi_type_pointer;
Thomas Heller5c6af802009-04-24 20:31:47 +0000904 stgdict->paramfunc = PyCPointerType_paramfunc;
Thomas Hellera06a1a82008-02-13 20:21:53 +0000905 stgdict->flags |= TYPEFLAG_ISPOINTER;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000906
907 proto = PyDict_GetItemString(typedict, "_type_"); /* Borrowed ref */
Thomas Heller5c6af802009-04-24 20:31:47 +0000908 if (proto && -1 == PyCPointerType_SetProto(stgdict, proto)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +0000909 Py_DECREF((PyObject *)stgdict);
910 return NULL;
911 }
912
Thomas Heller2e75c452008-06-05 17:51:15 +0000913 if (proto) {
914 StgDictObject *itemdict = PyType_stgdict(proto);
915 assert(itemdict);
Thomas Hellerc0b2a802008-07-15 17:03:08 +0000916 /* If itemdict->format is NULL, then this is a pointer to an
917 incomplete type. We create a generic format string
918 'pointer to bytes' in this case. XXX Better would be to
919 fix the format string later...
920 */
Thomas Heller5c6af802009-04-24 20:31:47 +0000921 stgdict->format = _ctypes_alloc_format_string("&",
Thomas Hellerc0b2a802008-07-15 17:03:08 +0000922 itemdict->format ? itemdict->format : "B");
Thomas Heller2e75c452008-06-05 17:51:15 +0000923 if (stgdict->format == NULL) {
924 Py_DECREF((PyObject *)stgdict);
925 return NULL;
926 }
927 }
928
Thomas Hellerd4c93202006-03-08 19:35:11 +0000929 /* create the new instance (which is a class,
930 since we are a metatype!) */
931 result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
932 if (result == NULL) {
933 Py_DECREF((PyObject *)stgdict);
934 return NULL;
935 }
936
937 /* replace the class dict by our updated spam dict */
938 if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) {
939 Py_DECREF(result);
940 Py_DECREF((PyObject *)stgdict);
941 return NULL;
942 }
943 Py_DECREF(result->tp_dict);
944 result->tp_dict = (PyObject *)stgdict;
945
946 return (PyObject *)result;
947}
948
949
950static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +0000951PyCPointerType_set_type(PyTypeObject *self, PyObject *type)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000952{
953 StgDictObject *dict;
954
955 dict = PyType_stgdict((PyObject *)self);
956 assert(dict);
957
Thomas Heller5c6af802009-04-24 20:31:47 +0000958 if (-1 == PyCPointerType_SetProto(dict, type))
Thomas Hellerd4c93202006-03-08 19:35:11 +0000959 return NULL;
960
961 if (-1 == PyDict_SetItemString((PyObject *)dict, "_type_", type))
962 return NULL;
963
964 Py_INCREF(Py_None);
965 return Py_None;
966}
967
968staticforward PyObject *_byref(PyObject *);
969
970static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +0000971PyCPointerType_from_param(PyObject *type, PyObject *value)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000972{
973 StgDictObject *typedict;
974
Thomas Heller6be522b2009-09-18 20:05:44 +0000975 if (value == Py_None) {
976 /* ConvParam will convert to a NULL pointer later */
977 Py_INCREF(value);
978 return value;
979 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000980
981 typedict = PyType_stgdict(type);
Thomas Heller0b21b432006-08-18 14:38:46 +0000982 assert(typedict); /* Cannot be NULL for pointer types */
Thomas Hellerd4c93202006-03-08 19:35:11 +0000983
984 /* If we expect POINTER(<type>), but receive a <type> instance, accept
985 it by calling byref(<type>).
986 */
987 switch (PyObject_IsInstance(value, typedict->proto)) {
988 case 1:
989 Py_INCREF(value); /* _byref steals a refcount */
990 return _byref(value);
991 case -1:
992 PyErr_Clear();
993 break;
994 default:
995 break;
996 }
997
998 if (PointerObject_Check(value) || ArrayObject_Check(value)) {
999 /* Array instances are also pointers when
1000 the item types are the same.
1001 */
1002 StgDictObject *v = PyObject_stgdict(value);
Thomas Hellerd32e6162006-08-16 13:03:11 +00001003 assert(v); /* Cannot be NULL for pointer or array objects */
Thomas Hellerd4c93202006-03-08 19:35:11 +00001004 if (PyObject_IsSubclass(v->proto, typedict->proto)) {
1005 Py_INCREF(value);
1006 return value;
1007 }
1008 }
1009 return CDataType_from_param(type, value);
1010}
1011
Thomas Heller5c6af802009-04-24 20:31:47 +00001012static PyMethodDef PyCPointerType_methods[] = {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001013 { "from_address", CDataType_from_address, METH_O, from_address_doc },
Thomas Heller6ad5fbb2008-04-25 15:44:16 +00001014 { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, },
1015 { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, },
Thomas Hellerd4c93202006-03-08 19:35:11 +00001016 { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc},
Thomas Heller5c6af802009-04-24 20:31:47 +00001017 { "from_param", (PyCFunction)PyCPointerType_from_param, METH_O, from_param_doc},
1018 { "set_type", (PyCFunction)PyCPointerType_set_type, METH_O },
Thomas Hellerd4c93202006-03-08 19:35:11 +00001019 { NULL, NULL },
1020};
1021
Thomas Heller5c6af802009-04-24 20:31:47 +00001022PyTypeObject PyCPointerType_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00001023 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Heller5c6af802009-04-24 20:31:47 +00001024 "_ctypes.PyCPointerType", /* tp_name */
Thomas Hellerd4c93202006-03-08 19:35:11 +00001025 0, /* tp_basicsize */
1026 0, /* tp_itemsize */
1027 0, /* tp_dealloc */
1028 0, /* tp_print */
1029 0, /* tp_getattr */
1030 0, /* tp_setattr */
1031 0, /* tp_compare */
1032 0, /* tp_repr */
1033 0, /* tp_as_number */
1034 &CDataType_as_sequence, /* tp_as_sequence */
1035 0, /* tp_as_mapping */
1036 0, /* tp_hash */
1037 0, /* tp_call */
1038 0, /* tp_str */
1039 0, /* tp_getattro */
1040 0, /* tp_setattro */
1041 0, /* tp_as_buffer */
1042 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1043 "metatype for the Pointer Objects", /* tp_doc */
1044 (traverseproc)CDataType_traverse, /* tp_traverse */
1045 (inquiry)CDataType_clear, /* tp_clear */
1046 0, /* tp_richcompare */
1047 0, /* tp_weaklistoffset */
1048 0, /* tp_iter */
1049 0, /* tp_iternext */
Thomas Heller5c6af802009-04-24 20:31:47 +00001050 PyCPointerType_methods, /* tp_methods */
Thomas Hellerd4c93202006-03-08 19:35:11 +00001051 0, /* tp_members */
1052 0, /* tp_getset */
1053 0, /* tp_base */
1054 0, /* tp_dict */
1055 0, /* tp_descr_get */
1056 0, /* tp_descr_set */
1057 0, /* tp_dictoffset */
1058 0, /* tp_init */
1059 0, /* tp_alloc */
Thomas Heller5c6af802009-04-24 20:31:47 +00001060 PyCPointerType_new, /* tp_new */
Thomas Hellerd4c93202006-03-08 19:35:11 +00001061 0, /* tp_free */
1062};
1063
1064
1065/******************************************************************/
1066/*
Thomas Heller5c6af802009-04-24 20:31:47 +00001067 PyCArrayType_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +00001068*/
1069/*
Thomas Heller5c6af802009-04-24 20:31:47 +00001070 PyCArrayType_new ensures that the new Array subclass created has a _length_
Thomas Hellerd4c93202006-03-08 19:35:11 +00001071 attribute, and a _type_ attribute.
1072*/
1073
1074static int
1075CharArray_set_raw(CDataObject *self, PyObject *value)
1076{
1077 char *ptr;
Thomas Hellerfe8f8622006-03-14 19:53:09 +00001078 Py_ssize_t size;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001079 if (PyBuffer_Check(value)) {
Christian Heimese93237d2007-12-19 02:37:44 +00001080 size = Py_TYPE(value)->tp_as_buffer->bf_getreadbuffer(value, 0, (void *)&ptr);
Thomas Hellerd4c93202006-03-08 19:35:11 +00001081 if (size < 0)
1082 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001083 } else if (-1 == PyString_AsStringAndSize(value, &ptr, &size)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001084 return -1;
1085 }
1086 if (size > self->b_size) {
1087 PyErr_SetString(PyExc_ValueError,
1088 "string too long");
1089 return -1;
1090 }
1091
1092 memcpy(self->b_ptr, ptr, size);
1093
1094 return 0;
1095}
1096
1097static PyObject *
1098CharArray_get_raw(CDataObject *self)
1099{
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001100 return PyString_FromStringAndSize(self->b_ptr, self->b_size);
Thomas Hellerd4c93202006-03-08 19:35:11 +00001101}
1102
1103static PyObject *
1104CharArray_get_value(CDataObject *self)
1105{
1106 int i;
1107 char *ptr = self->b_ptr;
1108 for (i = 0; i < self->b_size; ++i)
1109 if (*ptr++ == '\0')
1110 break;
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001111 return PyString_FromStringAndSize(self->b_ptr, i);
Thomas Hellerd4c93202006-03-08 19:35:11 +00001112}
1113
1114static int
1115CharArray_set_value(CDataObject *self, PyObject *value)
1116{
1117 char *ptr;
Thomas Hellere81c9f62007-06-08 18:20:09 +00001118 Py_ssize_t size;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001119
Thomas Heller153038e2007-12-18 19:00:34 +00001120 if (value == NULL) {
1121 PyErr_SetString(PyExc_TypeError,
1122 "can't delete attribute");
1123 return -1;
1124 }
1125
Thomas Hellerd4c93202006-03-08 19:35:11 +00001126 if (PyUnicode_Check(value)) {
1127 value = PyUnicode_AsEncodedString(value,
Thomas Heller5c6af802009-04-24 20:31:47 +00001128 _ctypes_conversion_encoding,
1129 _ctypes_conversion_errors);
Thomas Hellerd4c93202006-03-08 19:35:11 +00001130 if (!value)
1131 return -1;
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001132 } else if (!PyString_Check(value)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001133 PyErr_Format(PyExc_TypeError,
1134 "string expected instead of %s instance",
Christian Heimese93237d2007-12-19 02:37:44 +00001135 Py_TYPE(value)->tp_name);
Thomas Hellerd4c93202006-03-08 19:35:11 +00001136 return -1;
1137 } else
1138 Py_INCREF(value);
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001139 size = PyString_GET_SIZE(value);
Thomas Hellerd4c93202006-03-08 19:35:11 +00001140 if (size > self->b_size) {
1141 PyErr_SetString(PyExc_ValueError,
1142 "string too long");
1143 Py_DECREF(value);
1144 return -1;
1145 }
1146
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001147 ptr = PyString_AS_STRING(value);
Thomas Hellerd4c93202006-03-08 19:35:11 +00001148 memcpy(self->b_ptr, ptr, size);
1149 if (size < self->b_size)
1150 self->b_ptr[size] = '\0';
1151 Py_DECREF(value);
1152
1153 return 0;
1154}
1155
1156static PyGetSetDef CharArray_getsets[] = {
1157 { "raw", (getter)CharArray_get_raw, (setter)CharArray_set_raw,
1158 "value", NULL },
1159 { "value", (getter)CharArray_get_value, (setter)CharArray_set_value,
1160 "string value"},
1161 { NULL, NULL }
1162};
1163
1164#ifdef CTYPES_UNICODE
1165static PyObject *
1166WCharArray_get_value(CDataObject *self)
1167{
1168 unsigned int i;
1169 wchar_t *ptr = (wchar_t *)self->b_ptr;
1170 for (i = 0; i < self->b_size/sizeof(wchar_t); ++i)
1171 if (*ptr++ == (wchar_t)0)
1172 break;
1173 return PyUnicode_FromWideChar((wchar_t *)self->b_ptr, i);
1174}
1175
1176static int
1177WCharArray_set_value(CDataObject *self, PyObject *value)
1178{
Thomas Hellere81c9f62007-06-08 18:20:09 +00001179 Py_ssize_t result = 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001180
Thomas Heller153038e2007-12-18 19:00:34 +00001181 if (value == NULL) {
1182 PyErr_SetString(PyExc_TypeError,
1183 "can't delete attribute");
1184 return -1;
1185 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001186 if (PyString_Check(value)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001187 value = PyUnicode_FromEncodedObject(value,
Thomas Heller5c6af802009-04-24 20:31:47 +00001188 _ctypes_conversion_encoding,
1189 _ctypes_conversion_errors);
Thomas Hellerd4c93202006-03-08 19:35:11 +00001190 if (!value)
1191 return -1;
1192 } else if (!PyUnicode_Check(value)) {
1193 PyErr_Format(PyExc_TypeError,
1194 "unicode string expected instead of %s instance",
Christian Heimese93237d2007-12-19 02:37:44 +00001195 Py_TYPE(value)->tp_name);
Thomas Hellerd4c93202006-03-08 19:35:11 +00001196 return -1;
1197 } else
1198 Py_INCREF(value);
1199 if ((unsigned)PyUnicode_GET_SIZE(value) > self->b_size/sizeof(wchar_t)) {
1200 PyErr_SetString(PyExc_ValueError,
1201 "string too long");
1202 result = -1;
1203 goto done;
1204 }
1205 result = PyUnicode_AsWideChar((PyUnicodeObject *)value,
1206 (wchar_t *)self->b_ptr,
1207 self->b_size/sizeof(wchar_t));
Thomas Hellere81c9f62007-06-08 18:20:09 +00001208 if (result >= 0 && (size_t)result < self->b_size/sizeof(wchar_t))
Thomas Hellerd4c93202006-03-08 19:35:11 +00001209 ((wchar_t *)self->b_ptr)[result] = (wchar_t)0;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001210 done:
1211 Py_DECREF(value);
1212
Thomas Hellere81c9f62007-06-08 18:20:09 +00001213 return result >= 0 ? 0 : -1;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001214}
1215
1216static PyGetSetDef WCharArray_getsets[] = {
1217 { "value", (getter)WCharArray_get_value, (setter)WCharArray_set_value,
1218 "string value"},
1219 { NULL, NULL }
1220};
1221#endif
1222
1223/*
1224 The next three functions copied from Python's typeobject.c.
1225
1226 They are used to attach methods, members, or getsets to a type *after* it
1227 has been created: Arrays of characters have additional getsets to treat them
1228 as strings.
1229 */
1230/*
1231static int
1232add_methods(PyTypeObject *type, PyMethodDef *meth)
1233{
1234 PyObject *dict = type->tp_dict;
1235 for (; meth->ml_name != NULL; meth++) {
1236 PyObject *descr;
1237 descr = PyDescr_NewMethod(type, meth);
1238 if (descr == NULL)
1239 return -1;
1240 if (PyDict_SetItemString(dict,meth->ml_name, descr) < 0)
1241 return -1;
1242 Py_DECREF(descr);
1243 }
1244 return 0;
1245}
1246
1247static int
1248add_members(PyTypeObject *type, PyMemberDef *memb)
1249{
1250 PyObject *dict = type->tp_dict;
1251 for (; memb->name != NULL; memb++) {
1252 PyObject *descr;
1253 descr = PyDescr_NewMember(type, memb);
1254 if (descr == NULL)
1255 return -1;
1256 if (PyDict_SetItemString(dict, memb->name, descr) < 0)
1257 return -1;
1258 Py_DECREF(descr);
1259 }
1260 return 0;
1261}
1262*/
1263
1264static int
1265add_getset(PyTypeObject *type, PyGetSetDef *gsp)
1266{
1267 PyObject *dict = type->tp_dict;
1268 for (; gsp->name != NULL; gsp++) {
1269 PyObject *descr;
1270 descr = PyDescr_NewGetSet(type, gsp);
1271 if (descr == NULL)
1272 return -1;
1273 if (PyDict_SetItemString(dict, gsp->name, descr) < 0)
1274 return -1;
1275 Py_DECREF(descr);
1276 }
1277 return 0;
1278}
1279
Thomas Heller86720042006-08-14 11:17:48 +00001280static PyCArgObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00001281PyCArrayType_paramfunc(CDataObject *self)
Thomas Heller86720042006-08-14 11:17:48 +00001282{
Thomas Heller5c6af802009-04-24 20:31:47 +00001283 PyCArgObject *p = PyCArgObject_new();
Thomas Heller86720042006-08-14 11:17:48 +00001284 if (p == NULL)
1285 return NULL;
1286 p->tag = 'P';
1287 p->pffi_type = &ffi_type_pointer;
1288 p->value.p = (char *)self->b_ptr;
1289 Py_INCREF(self);
1290 p->obj = (PyObject *)self;
1291 return p;
1292}
Thomas Hellerd4c93202006-03-08 19:35:11 +00001293
1294static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00001295PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Thomas Hellerd4c93202006-03-08 19:35:11 +00001296{
1297 PyTypeObject *result;
1298 StgDictObject *stgdict;
1299 StgDictObject *itemdict;
1300 PyObject *proto;
1301 PyObject *typedict;
Thomas Heller2e75c452008-06-05 17:51:15 +00001302 long length;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001303
Thomas Hellere81c9f62007-06-08 18:20:09 +00001304 Py_ssize_t itemsize, itemalign;
Thomas Heller2e75c452008-06-05 17:51:15 +00001305 char buf[32];
Thomas Hellerd4c93202006-03-08 19:35:11 +00001306
1307 typedict = PyTuple_GetItem(args, 2);
1308 if (!typedict)
1309 return NULL;
1310
1311 proto = PyDict_GetItemString(typedict, "_length_"); /* Borrowed ref */
1312 if (!proto || !PyInt_Check(proto)) {
1313 PyErr_SetString(PyExc_AttributeError,
1314 "class must define a '_length_' attribute, "
1315 "which must be a positive integer");
1316 return NULL;
1317 }
1318 length = PyInt_AS_LONG(proto);
1319
1320 proto = PyDict_GetItemString(typedict, "_type_"); /* Borrowed ref */
1321 if (!proto) {
1322 PyErr_SetString(PyExc_AttributeError,
1323 "class must define a '_type_' attribute");
1324 return NULL;
1325 }
1326
1327 stgdict = (StgDictObject *)PyObject_CallObject(
Thomas Heller5c6af802009-04-24 20:31:47 +00001328 (PyObject *)&PyCStgDict_Type, NULL);
Thomas Hellerd4c93202006-03-08 19:35:11 +00001329 if (!stgdict)
1330 return NULL;
1331
1332 itemdict = PyType_stgdict(proto);
1333 if (!itemdict) {
1334 PyErr_SetString(PyExc_TypeError,
1335 "_type_ must have storage info");
1336 Py_DECREF((PyObject *)stgdict);
1337 return NULL;
1338 }
1339
Thomas Heller2e75c452008-06-05 17:51:15 +00001340 assert(itemdict->format);
1341 if (itemdict->format[0] == '(') {
1342 sprintf(buf, "(%ld,", length);
Thomas Heller5c6af802009-04-24 20:31:47 +00001343 stgdict->format = _ctypes_alloc_format_string(buf, itemdict->format+1);
Thomas Heller2e75c452008-06-05 17:51:15 +00001344 } else {
1345 sprintf(buf, "(%ld)", length);
Thomas Heller5c6af802009-04-24 20:31:47 +00001346 stgdict->format = _ctypes_alloc_format_string(buf, itemdict->format);
Thomas Heller2e75c452008-06-05 17:51:15 +00001347 }
1348 if (stgdict->format == NULL) {
1349 Py_DECREF((PyObject *)stgdict);
1350 return NULL;
1351 }
1352 stgdict->ndim = itemdict->ndim + 1;
1353 stgdict->shape = PyMem_Malloc(sizeof(Py_ssize_t *) * stgdict->ndim);
1354 if (stgdict->shape == NULL) {
1355 Py_DECREF((PyObject *)stgdict);
1356 return NULL;
1357 }
1358 stgdict->shape[0] = length;
1359 memmove(&stgdict->shape[1], itemdict->shape,
1360 sizeof(Py_ssize_t) * (stgdict->ndim - 1));
1361
Thomas Hellerd4c93202006-03-08 19:35:11 +00001362 itemsize = itemdict->size;
Thomas Hellere6a70392007-03-23 19:55:27 +00001363 if (length * itemsize < 0) {
1364 PyErr_SetString(PyExc_OverflowError,
1365 "array too large");
1366 return NULL;
1367 }
1368
Thomas Hellerd4c93202006-03-08 19:35:11 +00001369 itemalign = itemdict->align;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001370
Thomas Hellera06a1a82008-02-13 20:21:53 +00001371 if (itemdict->flags & (TYPEFLAG_ISPOINTER | TYPEFLAG_HASPOINTER))
1372 stgdict->flags |= TYPEFLAG_HASPOINTER;
1373
Thomas Hellerd4c93202006-03-08 19:35:11 +00001374 stgdict->size = itemsize * length;
1375 stgdict->align = itemalign;
1376 stgdict->length = length;
1377 Py_INCREF(proto);
1378 stgdict->proto = proto;
1379
Thomas Heller5c6af802009-04-24 20:31:47 +00001380 stgdict->paramfunc = &PyCArrayType_paramfunc;
Thomas Heller86720042006-08-14 11:17:48 +00001381
Thomas Hellerd4c93202006-03-08 19:35:11 +00001382 /* Arrays are passed as pointers to function calls. */
Skip Montanaro058be9a2006-04-18 19:45:17 +00001383 stgdict->ffi_type_pointer = ffi_type_pointer;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001384
1385 /* create the new instance (which is a class,
1386 since we are a metatype!) */
1387 result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
1388 if (result == NULL)
1389 return NULL;
1390
1391 /* replace the class dict by our updated spam dict */
1392 if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) {
1393 Py_DECREF(result);
1394 Py_DECREF((PyObject *)stgdict);
1395 return NULL;
1396 }
1397 Py_DECREF(result->tp_dict);
1398 result->tp_dict = (PyObject *)stgdict;
1399
1400 /* Special case for character arrays.
1401 A permanent annoyance: char arrays are also strings!
1402 */
Thomas Heller5c6af802009-04-24 20:31:47 +00001403 if (itemdict->getfunc == _ctypes_get_fielddesc("c")->getfunc) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001404 if (-1 == add_getset(result, CharArray_getsets))
1405 return NULL;
1406#ifdef CTYPES_UNICODE
Thomas Heller5c6af802009-04-24 20:31:47 +00001407 } else if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001408 if (-1 == add_getset(result, WCharArray_getsets))
1409 return NULL;
1410#endif
1411 }
1412
1413 return (PyObject *)result;
1414}
1415
Thomas Heller5c6af802009-04-24 20:31:47 +00001416PyTypeObject PyCArrayType_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00001417 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Heller5c6af802009-04-24 20:31:47 +00001418 "_ctypes.PyCArrayType", /* tp_name */
Thomas Hellerd4c93202006-03-08 19:35:11 +00001419 0, /* tp_basicsize */
1420 0, /* tp_itemsize */
1421 0, /* tp_dealloc */
1422 0, /* tp_print */
1423 0, /* tp_getattr */
1424 0, /* tp_setattr */
1425 0, /* tp_compare */
1426 0, /* tp_repr */
1427 0, /* tp_as_number */
1428 &CDataType_as_sequence, /* tp_as_sequence */
1429 0, /* tp_as_mapping */
1430 0, /* tp_hash */
1431 0, /* tp_call */
1432 0, /* tp_str */
1433 0, /* tp_getattro */
1434 0, /* tp_setattro */
1435 0, /* tp_as_buffer */
1436 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
1437 "metatype for the Array Objects", /* tp_doc */
1438 0, /* tp_traverse */
1439 0, /* tp_clear */
1440 0, /* tp_richcompare */
1441 0, /* tp_weaklistoffset */
1442 0, /* tp_iter */
1443 0, /* tp_iternext */
1444 CDataType_methods, /* tp_methods */
1445 0, /* tp_members */
1446 0, /* tp_getset */
1447 0, /* tp_base */
1448 0, /* tp_dict */
1449 0, /* tp_descr_get */
1450 0, /* tp_descr_set */
1451 0, /* tp_dictoffset */
1452 0, /* tp_init */
1453 0, /* tp_alloc */
Thomas Heller5c6af802009-04-24 20:31:47 +00001454 PyCArrayType_new, /* tp_new */
Thomas Hellerd4c93202006-03-08 19:35:11 +00001455 0, /* tp_free */
1456};
1457
1458
1459/******************************************************************/
1460/*
Thomas Heller5c6af802009-04-24 20:31:47 +00001461 PyCSimpleType_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +00001462*/
1463/*
1464
Thomas Heller5c6af802009-04-24 20:31:47 +00001465PyCSimpleType_new ensures that the new Simple_Type subclass created has a valid
Thomas Hellerd4c93202006-03-08 19:35:11 +00001466_type_ attribute.
1467
1468*/
1469
Thomas Hellerf3c05592008-03-05 15:34:29 +00001470static char *SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv?g";
Thomas Hellerd4c93202006-03-08 19:35:11 +00001471
1472static PyObject *
1473c_wchar_p_from_param(PyObject *type, PyObject *value)
1474{
Thomas Heller86720042006-08-14 11:17:48 +00001475 PyObject *as_parameter;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001476#if (PYTHON_API_VERSION < 1012)
1477# error not supported
1478#endif
1479 if (value == Py_None) {
1480 Py_INCREF(Py_None);
1481 return Py_None;
1482 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001483 if (PyUnicode_Check(value) || PyString_Check(value)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001484 PyCArgObject *parg;
Thomas Heller5c6af802009-04-24 20:31:47 +00001485 struct fielddesc *fd = _ctypes_get_fielddesc("Z");
Thomas Hellerd4c93202006-03-08 19:35:11 +00001486
Thomas Heller5c6af802009-04-24 20:31:47 +00001487 parg = PyCArgObject_new();
Thomas Hellerefa27272006-08-14 07:14:09 +00001488 if (parg == NULL)
1489 return NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001490 parg->pffi_type = &ffi_type_pointer;
1491 parg->tag = 'Z';
1492 parg->obj = fd->setfunc(&parg->value, value, 0);
1493 if (parg->obj == NULL) {
1494 Py_DECREF(parg);
1495 return NULL;
1496 }
1497 return (PyObject *)parg;
1498 }
1499 if (PyObject_IsInstance(value, type)) {
1500 Py_INCREF(value);
1501 return value;
1502 }
1503 if (ArrayObject_Check(value) || PointerObject_Check(value)) {
1504 /* c_wchar array instance or pointer(c_wchar(...)) */
1505 StgDictObject *dt = PyObject_stgdict(value);
Thomas Hellerd32e6162006-08-16 13:03:11 +00001506 StgDictObject *dict;
1507 assert(dt); /* Cannot be NULL for pointer or array objects */
1508 dict = dt && dt->proto ? PyType_stgdict(dt->proto) : NULL;
Thomas Heller5c6af802009-04-24 20:31:47 +00001509 if (dict && (dict->setfunc == _ctypes_get_fielddesc("u")->setfunc)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001510 Py_INCREF(value);
1511 return value;
1512 }
1513 }
1514 if (PyCArg_CheckExact(value)) {
1515 /* byref(c_char(...)) */
1516 PyCArgObject *a = (PyCArgObject *)value;
1517 StgDictObject *dict = PyObject_stgdict(a->obj);
Thomas Heller5c6af802009-04-24 20:31:47 +00001518 if (dict && (dict->setfunc == _ctypes_get_fielddesc("u")->setfunc)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001519 Py_INCREF(value);
1520 return value;
1521 }
1522 }
Thomas Heller86720042006-08-14 11:17:48 +00001523
1524 as_parameter = PyObject_GetAttrString(value, "_as_parameter_");
1525 if (as_parameter) {
1526 value = c_wchar_p_from_param(type, as_parameter);
1527 Py_DECREF(as_parameter);
1528 return value;
1529 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00001530 /* XXX better message */
1531 PyErr_SetString(PyExc_TypeError,
1532 "wrong type");
1533 return NULL;
1534}
1535
1536static PyObject *
1537c_char_p_from_param(PyObject *type, PyObject *value)
1538{
Thomas Heller86720042006-08-14 11:17:48 +00001539 PyObject *as_parameter;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001540#if (PYTHON_API_VERSION < 1012)
1541# error not supported
1542#endif
1543 if (value == Py_None) {
1544 Py_INCREF(Py_None);
1545 return Py_None;
1546 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001547 if (PyString_Check(value) || PyUnicode_Check(value)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001548 PyCArgObject *parg;
Thomas Heller5c6af802009-04-24 20:31:47 +00001549 struct fielddesc *fd = _ctypes_get_fielddesc("z");
Thomas Hellerd4c93202006-03-08 19:35:11 +00001550
Thomas Heller5c6af802009-04-24 20:31:47 +00001551 parg = PyCArgObject_new();
Thomas Hellerefa27272006-08-14 07:14:09 +00001552 if (parg == NULL)
1553 return NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001554 parg->pffi_type = &ffi_type_pointer;
1555 parg->tag = 'z';
1556 parg->obj = fd->setfunc(&parg->value, value, 0);
1557 if (parg->obj == NULL) {
1558 Py_DECREF(parg);
1559 return NULL;
1560 }
1561 return (PyObject *)parg;
1562 }
1563 if (PyObject_IsInstance(value, type)) {
1564 Py_INCREF(value);
1565 return value;
1566 }
1567 if (ArrayObject_Check(value) || PointerObject_Check(value)) {
1568 /* c_char array instance or pointer(c_char(...)) */
1569 StgDictObject *dt = PyObject_stgdict(value);
Thomas Hellerd32e6162006-08-16 13:03:11 +00001570 StgDictObject *dict;
1571 assert(dt); /* Cannot be NULL for pointer or array objects */
1572 dict = dt && dt->proto ? PyType_stgdict(dt->proto) : NULL;
Thomas Heller5c6af802009-04-24 20:31:47 +00001573 if (dict && (dict->setfunc == _ctypes_get_fielddesc("c")->setfunc)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001574 Py_INCREF(value);
1575 return value;
1576 }
1577 }
1578 if (PyCArg_CheckExact(value)) {
1579 /* byref(c_char(...)) */
1580 PyCArgObject *a = (PyCArgObject *)value;
1581 StgDictObject *dict = PyObject_stgdict(a->obj);
Thomas Heller5c6af802009-04-24 20:31:47 +00001582 if (dict && (dict->setfunc == _ctypes_get_fielddesc("c")->setfunc)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001583 Py_INCREF(value);
1584 return value;
1585 }
1586 }
Thomas Heller86720042006-08-14 11:17:48 +00001587
1588 as_parameter = PyObject_GetAttrString(value, "_as_parameter_");
1589 if (as_parameter) {
1590 value = c_char_p_from_param(type, as_parameter);
1591 Py_DECREF(as_parameter);
1592 return value;
1593 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00001594 /* XXX better message */
1595 PyErr_SetString(PyExc_TypeError,
1596 "wrong type");
1597 return NULL;
1598}
1599
1600static PyObject *
1601c_void_p_from_param(PyObject *type, PyObject *value)
1602{
1603 StgDictObject *stgd;
Thomas Heller86720042006-08-14 11:17:48 +00001604 PyObject *as_parameter;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001605#if (PYTHON_API_VERSION < 1012)
1606# error not supported
1607#endif
1608
1609/* None */
1610 if (value == Py_None) {
1611 Py_INCREF(Py_None);
1612 return Py_None;
1613 }
1614 /* Should probably allow buffer interface as well */
1615/* int, long */
1616 if (PyInt_Check(value) || PyLong_Check(value)) {
1617 PyCArgObject *parg;
Thomas Heller5c6af802009-04-24 20:31:47 +00001618 struct fielddesc *fd = _ctypes_get_fielddesc("P");
Thomas Hellerd4c93202006-03-08 19:35:11 +00001619
Thomas Heller5c6af802009-04-24 20:31:47 +00001620 parg = PyCArgObject_new();
Thomas Hellerefa27272006-08-14 07:14:09 +00001621 if (parg == NULL)
1622 return NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001623 parg->pffi_type = &ffi_type_pointer;
1624 parg->tag = 'P';
1625 parg->obj = fd->setfunc(&parg->value, value, 0);
1626 if (parg->obj == NULL) {
1627 Py_DECREF(parg);
1628 return NULL;
1629 }
1630 return (PyObject *)parg;
1631 }
1632/* string */
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001633 if (PyString_Check(value)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001634 PyCArgObject *parg;
Thomas Heller5c6af802009-04-24 20:31:47 +00001635 struct fielddesc *fd = _ctypes_get_fielddesc("z");
Thomas Hellerd4c93202006-03-08 19:35:11 +00001636
Thomas Heller5c6af802009-04-24 20:31:47 +00001637 parg = PyCArgObject_new();
Thomas Heller4dc5dd12006-08-15 13:07:21 +00001638 if (parg == NULL)
1639 return NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001640 parg->pffi_type = &ffi_type_pointer;
1641 parg->tag = 'z';
1642 parg->obj = fd->setfunc(&parg->value, value, 0);
1643 if (parg->obj == NULL) {
1644 Py_DECREF(parg);
1645 return NULL;
1646 }
1647 return (PyObject *)parg;
1648 }
1649/* unicode */
1650 if (PyUnicode_Check(value)) {
1651 PyCArgObject *parg;
Thomas Heller5c6af802009-04-24 20:31:47 +00001652 struct fielddesc *fd = _ctypes_get_fielddesc("Z");
Thomas Hellerd4c93202006-03-08 19:35:11 +00001653
Thomas Heller5c6af802009-04-24 20:31:47 +00001654 parg = PyCArgObject_new();
Thomas Heller4dc5dd12006-08-15 13:07:21 +00001655 if (parg == NULL)
1656 return NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001657 parg->pffi_type = &ffi_type_pointer;
1658 parg->tag = 'Z';
1659 parg->obj = fd->setfunc(&parg->value, value, 0);
1660 if (parg->obj == NULL) {
1661 Py_DECREF(parg);
1662 return NULL;
1663 }
1664 return (PyObject *)parg;
1665 }
1666/* c_void_p instance (or subclass) */
1667 if (PyObject_IsInstance(value, type)) {
1668 /* c_void_p instances */
1669 Py_INCREF(value);
1670 return value;
1671 }
1672/* ctypes array or pointer instance */
1673 if (ArrayObject_Check(value) || PointerObject_Check(value)) {
1674 /* Any array or pointer is accepted */
1675 Py_INCREF(value);
1676 return value;
1677 }
1678/* byref(...) */
1679 if (PyCArg_CheckExact(value)) {
1680 /* byref(c_xxx()) */
1681 PyCArgObject *a = (PyCArgObject *)value;
1682 if (a->tag == 'P') {
1683 Py_INCREF(value);
1684 return value;
1685 }
1686 }
Thomas Heller4b75a7c2006-04-21 16:48:56 +00001687/* function pointer */
Thomas Heller5c6af802009-04-24 20:31:47 +00001688 if (PyCFuncPtrObject_Check(value)) {
Thomas Heller4b75a7c2006-04-21 16:48:56 +00001689 PyCArgObject *parg;
Thomas Heller5c6af802009-04-24 20:31:47 +00001690 PyCFuncPtrObject *func;
1691 func = (PyCFuncPtrObject *)value;
1692 parg = PyCArgObject_new();
Thomas Heller4dc5dd12006-08-15 13:07:21 +00001693 if (parg == NULL)
1694 return NULL;
Thomas Heller4b75a7c2006-04-21 16:48:56 +00001695 parg->pffi_type = &ffi_type_pointer;
1696 parg->tag = 'P';
1697 Py_INCREF(value);
1698 parg->value.p = *(void **)func->b_ptr;
1699 parg->obj = value;
1700 return (PyObject *)parg;
1701 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00001702/* c_char_p, c_wchar_p */
1703 stgd = PyObject_stgdict(value);
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001704 if (stgd && CDataObject_Check(value) && stgd->proto && PyString_Check(stgd->proto)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001705 PyCArgObject *parg;
1706
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001707 switch (PyString_AS_STRING(stgd->proto)[0]) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001708 case 'z': /* c_char_p */
1709 case 'Z': /* c_wchar_p */
Thomas Heller5c6af802009-04-24 20:31:47 +00001710 parg = PyCArgObject_new();
Thomas Hellerd4c93202006-03-08 19:35:11 +00001711 if (parg == NULL)
1712 return NULL;
1713 parg->pffi_type = &ffi_type_pointer;
1714 parg->tag = 'Z';
1715 Py_INCREF(value);
1716 parg->obj = value;
1717 /* Remember: b_ptr points to where the pointer is stored! */
1718 parg->value.p = *(void **)(((CDataObject *)value)->b_ptr);
1719 return (PyObject *)parg;
1720 }
1721 }
Thomas Heller86720042006-08-14 11:17:48 +00001722
1723 as_parameter = PyObject_GetAttrString(value, "_as_parameter_");
1724 if (as_parameter) {
1725 value = c_void_p_from_param(type, as_parameter);
1726 Py_DECREF(as_parameter);
1727 return value;
1728 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00001729 /* XXX better message */
1730 PyErr_SetString(PyExc_TypeError,
1731 "wrong type");
1732 return NULL;
1733}
1734#if (PYTHON_API_VERSION >= 1012)
1735
1736static PyMethodDef c_void_p_method = { "from_param", c_void_p_from_param, METH_O };
1737static PyMethodDef c_char_p_method = { "from_param", c_char_p_from_param, METH_O };
1738static PyMethodDef c_wchar_p_method = { "from_param", c_wchar_p_from_param, METH_O };
1739
1740#else
1741#error
1742static PyMethodDef c_void_p_method = { "from_param", c_void_p_from_param, METH_VARARGS };
1743static PyMethodDef c_char_p_method = { "from_param", c_char_p_from_param, METH_VARARGS };
1744static PyMethodDef c_wchar_p_method = { "from_param", c_wchar_p_from_param, METH_VARARGS };
1745
1746#endif
1747
1748static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject *kwds,
1749 PyObject *proto, struct fielddesc *fmt)
1750{
1751 PyTypeObject *result;
1752 StgDictObject *stgdict;
1753 PyObject *name = PyTuple_GET_ITEM(args, 0);
Thomas Heller4c9dfc82006-03-16 19:26:21 +00001754 PyObject *swapped_args;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001755 static PyObject *suffix;
Neal Norwitzb0383332006-04-06 08:05:53 +00001756 Py_ssize_t i;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001757
Thomas Heller4c9dfc82006-03-16 19:26:21 +00001758 swapped_args = PyTuple_New(PyTuple_GET_SIZE(args));
1759 if (!swapped_args)
1760 return NULL;
1761
Thomas Hellerd4c93202006-03-08 19:35:11 +00001762 if (suffix == NULL)
1763#ifdef WORDS_BIGENDIAN
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001764 suffix = PyString_InternFromString("_le");
Thomas Hellerd4c93202006-03-08 19:35:11 +00001765#else
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001766 suffix = PyString_InternFromString("_be");
Thomas Hellerd4c93202006-03-08 19:35:11 +00001767#endif
1768
Thomas Heller9d892992006-04-18 14:57:39 +00001769 Py_INCREF(name);
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001770 PyString_Concat(&name, suffix);
Neal Norwitzb0383332006-04-06 08:05:53 +00001771 if (name == NULL)
1772 return NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001773
1774 PyTuple_SET_ITEM(swapped_args, 0, name);
1775 for (i=1; i<PyTuple_GET_SIZE(args); ++i) {
1776 PyObject *v = PyTuple_GET_ITEM(args, i);
1777 Py_INCREF(v);
1778 PyTuple_SET_ITEM(swapped_args, i, v);
1779 }
1780
1781 /* create the new instance (which is a class,
1782 since we are a metatype!) */
1783 result = (PyTypeObject *)PyType_Type.tp_new(type, swapped_args, kwds);
1784 Py_DECREF(swapped_args);
1785 if (result == NULL)
1786 return NULL;
1787
1788 stgdict = (StgDictObject *)PyObject_CallObject(
Thomas Heller5c6af802009-04-24 20:31:47 +00001789 (PyObject *)&PyCStgDict_Type, NULL);
Thomas Hellerd4c93202006-03-08 19:35:11 +00001790 if (!stgdict) /* XXX leaks result! */
1791 return NULL;
1792
Skip Montanaro058be9a2006-04-18 19:45:17 +00001793 stgdict->ffi_type_pointer = *fmt->pffi_type;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001794 stgdict->align = fmt->pffi_type->alignment;
1795 stgdict->length = 0;
1796 stgdict->size = fmt->pffi_type->size;
1797 stgdict->setfunc = fmt->setfunc_swapped;
1798 stgdict->getfunc = fmt->getfunc_swapped;
1799
1800 Py_INCREF(proto);
1801 stgdict->proto = proto;
1802
1803 /* replace the class dict by our updated spam dict */
1804 if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) {
1805 Py_DECREF(result);
1806 Py_DECREF((PyObject *)stgdict);
1807 return NULL;
1808 }
1809 Py_DECREF(result->tp_dict);
1810 result->tp_dict = (PyObject *)stgdict;
1811
1812 return (PyObject *)result;
1813}
1814
Thomas Heller86720042006-08-14 11:17:48 +00001815static PyCArgObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00001816PyCSimpleType_paramfunc(CDataObject *self)
Thomas Heller86720042006-08-14 11:17:48 +00001817{
1818 StgDictObject *dict;
1819 char *fmt;
1820 PyCArgObject *parg;
1821 struct fielddesc *fd;
1822
1823 dict = PyObject_stgdict((PyObject *)self);
Thomas Hellerd32e6162006-08-16 13:03:11 +00001824 assert(dict); /* Cannot be NULL for CDataObject instances */
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001825 fmt = PyString_AsString(dict->proto);
Thomas Heller86720042006-08-14 11:17:48 +00001826 assert(fmt);
1827
Thomas Heller5c6af802009-04-24 20:31:47 +00001828 fd = _ctypes_get_fielddesc(fmt);
Thomas Heller86720042006-08-14 11:17:48 +00001829 assert(fd);
1830
Thomas Heller5c6af802009-04-24 20:31:47 +00001831 parg = PyCArgObject_new();
Thomas Heller86720042006-08-14 11:17:48 +00001832 if (parg == NULL)
1833 return NULL;
1834
1835 parg->tag = fmt[0];
1836 parg->pffi_type = fd->pffi_type;
1837 Py_INCREF(self);
1838 parg->obj = (PyObject *)self;
1839 memcpy(&parg->value, self->b_ptr, self->b_size);
1840 return parg;
1841}
Thomas Hellerd4c93202006-03-08 19:35:11 +00001842
1843static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00001844PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Thomas Hellerd4c93202006-03-08 19:35:11 +00001845{
1846 PyTypeObject *result;
1847 StgDictObject *stgdict;
1848 PyObject *proto;
Thomas Heller2e75c452008-06-05 17:51:15 +00001849 const char *proto_str;
1850 Py_ssize_t proto_len;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001851 PyMethodDef *ml;
1852 struct fielddesc *fmt;
1853
1854 /* create the new instance (which is a class,
1855 since we are a metatype!) */
1856 result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
1857 if (result == NULL)
1858 return NULL;
1859
1860 proto = PyObject_GetAttrString((PyObject *)result, "_type_"); /* new ref */
Thomas Heller2e75c452008-06-05 17:51:15 +00001861 if (!proto) {
1862 PyErr_SetString(PyExc_AttributeError,
1863 "class must define a '_type_' attribute");
1864 error:
1865 Py_XDECREF(proto);
1866 Py_XDECREF(result);
1867 return NULL;
1868 }
1869 if (PyString_Check(proto)) {
Thomas Hellerba559362008-07-24 11:16:45 +00001870 proto_str = PyString_AS_STRING(proto);
1871 proto_len = PyString_GET_SIZE(proto);
Thomas Heller2e75c452008-06-05 17:51:15 +00001872 } else {
1873 PyErr_SetString(PyExc_TypeError,
1874 "class must define a '_type_' string attribute");
1875 goto error;
1876 }
1877 if (proto_len != 1) {
1878 PyErr_SetString(PyExc_ValueError,
1879 "class must define a '_type_' attribute "
1880 "which must be a string of length 1");
1881 goto error;
1882 }
1883 if (!strchr(SIMPLE_TYPE_CHARS, *proto_str)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001884 PyErr_Format(PyExc_AttributeError,
1885 "class must define a '_type_' attribute which must be\n"
1886 "a single character string containing one of '%s'.",
1887 SIMPLE_TYPE_CHARS);
Thomas Heller2e75c452008-06-05 17:51:15 +00001888 goto error;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001889 }
Thomas Heller5c6af802009-04-24 20:31:47 +00001890 fmt = _ctypes_get_fielddesc(PyString_AS_STRING(proto));
Thomas Heller7b1da512006-07-10 09:31:06 +00001891 if (fmt == NULL) {
1892 Py_DECREF(result);
1893 PyErr_Format(PyExc_ValueError,
1894 "_type_ '%s' not supported",
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001895 PyString_AS_STRING(proto));
Thomas Heller7b1da512006-07-10 09:31:06 +00001896 return NULL;
1897 }
1898
Thomas Hellerd4c93202006-03-08 19:35:11 +00001899 stgdict = (StgDictObject *)PyObject_CallObject(
Thomas Heller5c6af802009-04-24 20:31:47 +00001900 (PyObject *)&PyCStgDict_Type, NULL);
Thomas Hellerd4c93202006-03-08 19:35:11 +00001901 if (!stgdict)
1902 return NULL;
1903
Skip Montanaro058be9a2006-04-18 19:45:17 +00001904 stgdict->ffi_type_pointer = *fmt->pffi_type;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001905 stgdict->align = fmt->pffi_type->alignment;
1906 stgdict->length = 0;
1907 stgdict->size = fmt->pffi_type->size;
1908 stgdict->setfunc = fmt->setfunc;
1909 stgdict->getfunc = fmt->getfunc;
Thomas Heller2e75c452008-06-05 17:51:15 +00001910#ifdef WORDS_BIGENDIAN
Thomas Heller5c6af802009-04-24 20:31:47 +00001911 stgdict->format = _ctypes_alloc_format_string(">", proto_str);
Thomas Heller2e75c452008-06-05 17:51:15 +00001912#else
Thomas Heller5c6af802009-04-24 20:31:47 +00001913 stgdict->format = _ctypes_alloc_format_string("<", proto_str);
Thomas Heller2e75c452008-06-05 17:51:15 +00001914#endif
1915 if (stgdict->format == NULL) {
1916 Py_DECREF(result);
1917 Py_DECREF((PyObject *)stgdict);
1918 return NULL;
1919 }
Thomas Heller86720042006-08-14 11:17:48 +00001920
Thomas Heller5c6af802009-04-24 20:31:47 +00001921 stgdict->paramfunc = PyCSimpleType_paramfunc;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001922/*
1923 if (result->tp_base != &Simple_Type) {
1924 stgdict->setfunc = NULL;
1925 stgdict->getfunc = NULL;
1926 }
1927*/
1928
1929 /* This consumes the refcount on proto which we have */
1930 stgdict->proto = proto;
1931
1932 /* replace the class dict by our updated spam dict */
1933 if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) {
1934 Py_DECREF(result);
1935 Py_DECREF((PyObject *)stgdict);
1936 return NULL;
1937 }
1938 Py_DECREF(result->tp_dict);
1939 result->tp_dict = (PyObject *)stgdict;
1940
1941 /* Install from_param class methods in ctypes base classes.
Thomas Heller5c6af802009-04-24 20:31:47 +00001942 Overrides the PyCSimpleType_from_param generic method.
Thomas Hellerd4c93202006-03-08 19:35:11 +00001943 */
1944 if (result->tp_base == &Simple_Type) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +00001945 switch (PyString_AS_STRING(proto)[0]) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00001946 case 'z': /* c_char_p */
1947 ml = &c_char_p_method;
Thomas Hellera06a1a82008-02-13 20:21:53 +00001948 stgdict->flags |= TYPEFLAG_ISPOINTER;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001949 break;
1950 case 'Z': /* c_wchar_p */
1951 ml = &c_wchar_p_method;
Thomas Hellera06a1a82008-02-13 20:21:53 +00001952 stgdict->flags |= TYPEFLAG_ISPOINTER;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001953 break;
1954 case 'P': /* c_void_p */
1955 ml = &c_void_p_method;
Thomas Hellera06a1a82008-02-13 20:21:53 +00001956 stgdict->flags |= TYPEFLAG_ISPOINTER;
1957 break;
Thomas Hellerec21ccd2009-04-24 20:00:41 +00001958 case 's':
Thomas Hellera06a1a82008-02-13 20:21:53 +00001959 case 'X':
1960 case 'O':
1961 ml = NULL;
1962 stgdict->flags |= TYPEFLAG_ISPOINTER;
Thomas Hellerd4c93202006-03-08 19:35:11 +00001963 break;
1964 default:
1965 ml = NULL;
1966 break;
1967 }
1968
1969 if (ml) {
1970#if (PYTHON_API_VERSION >= 1012)
1971 PyObject *meth;
1972 int x;
1973 meth = PyDescr_NewClassMethod(result, ml);
1974 if (!meth)
1975 return NULL;
1976#else
1977#error
1978 PyObject *meth, *func;
1979 int x;
1980 func = PyCFunction_New(ml, NULL);
1981 if (!func)
1982 return NULL;
1983 meth = PyObject_CallFunctionObjArgs(
1984 (PyObject *)&PyClassMethod_Type,
1985 func, NULL);
1986 Py_DECREF(func);
1987 if (!meth) {
1988 return NULL;
1989 }
1990#endif
1991 x = PyDict_SetItemString(result->tp_dict,
1992 ml->ml_name,
1993 meth);
1994 Py_DECREF(meth);
1995 if (x == -1) {
1996 Py_DECREF(result);
1997 return NULL;
1998 }
1999 }
2000 }
2001
Thomas Heller5c6af802009-04-24 20:31:47 +00002002 if (type == &PyCSimpleType_Type && fmt->setfunc_swapped && fmt->getfunc_swapped) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00002003 PyObject *swapped = CreateSwappedType(type, args, kwds,
2004 proto, fmt);
Thomas Heller2e75c452008-06-05 17:51:15 +00002005 StgDictObject *sw_dict;
Thomas Hellerd4c93202006-03-08 19:35:11 +00002006 if (swapped == NULL) {
2007 Py_DECREF(result);
2008 return NULL;
2009 }
Thomas Heller2e75c452008-06-05 17:51:15 +00002010 sw_dict = PyType_stgdict(swapped);
Thomas Hellerd4c93202006-03-08 19:35:11 +00002011#ifdef WORDS_BIGENDIAN
2012 PyObject_SetAttrString((PyObject *)result, "__ctype_le__", swapped);
2013 PyObject_SetAttrString((PyObject *)result, "__ctype_be__", (PyObject *)result);
2014 PyObject_SetAttrString(swapped, "__ctype_be__", (PyObject *)result);
2015 PyObject_SetAttrString(swapped, "__ctype_le__", swapped);
Thomas Heller2e75c452008-06-05 17:51:15 +00002016 /* We are creating the type for the OTHER endian */
Thomas Heller5c6af802009-04-24 20:31:47 +00002017 sw_dict->format = _ctypes_alloc_format_string("<", stgdict->format+1);
Thomas Hellerd4c93202006-03-08 19:35:11 +00002018#else
2019 PyObject_SetAttrString((PyObject *)result, "__ctype_be__", swapped);
2020 PyObject_SetAttrString((PyObject *)result, "__ctype_le__", (PyObject *)result);
2021 PyObject_SetAttrString(swapped, "__ctype_le__", (PyObject *)result);
2022 PyObject_SetAttrString(swapped, "__ctype_be__", swapped);
Thomas Heller2e75c452008-06-05 17:51:15 +00002023 /* We are creating the type for the OTHER endian */
Thomas Heller5c6af802009-04-24 20:31:47 +00002024 sw_dict->format = _ctypes_alloc_format_string(">", stgdict->format+1);
Thomas Hellerd4c93202006-03-08 19:35:11 +00002025#endif
Thomas Heller9d892992006-04-18 14:57:39 +00002026 Py_DECREF(swapped);
Thomas Heller2e75c452008-06-05 17:51:15 +00002027 if (PyErr_Occurred()) {
2028 Py_DECREF(result);
2029 return NULL;
2030 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00002031 };
2032
2033 return (PyObject *)result;
2034}
2035
2036/*
2037 * This is a *class method*.
2038 * Convert a parameter into something that ConvParam can handle.
Thomas Hellerd4c93202006-03-08 19:35:11 +00002039 */
2040static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00002041PyCSimpleType_from_param(PyObject *type, PyObject *value)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002042{
2043 StgDictObject *dict;
2044 char *fmt;
2045 PyCArgObject *parg;
2046 struct fielddesc *fd;
Thomas Heller86720042006-08-14 11:17:48 +00002047 PyObject *as_parameter;
Thomas Hellerd4c93202006-03-08 19:35:11 +00002048
2049 /* If the value is already an instance of the requested type,
2050 we can use it as is */
2051 if (1 == PyObject_IsInstance(value, type)) {
2052 Py_INCREF(value);
2053 return value;
2054 }
2055
2056 dict = PyType_stgdict(type);
2057 assert(dict);
2058
2059 /* I think we can rely on this being a one-character string */
Gregory P. Smithdd96db62008-06-09 04:58:54 +00002060 fmt = PyString_AsString(dict->proto);
Thomas Hellerd4c93202006-03-08 19:35:11 +00002061 assert(fmt);
2062
Thomas Heller5c6af802009-04-24 20:31:47 +00002063 fd = _ctypes_get_fielddesc(fmt);
Thomas Hellerd4c93202006-03-08 19:35:11 +00002064 assert(fd);
2065
Thomas Heller5c6af802009-04-24 20:31:47 +00002066 parg = PyCArgObject_new();
Thomas Hellerd4c93202006-03-08 19:35:11 +00002067 if (parg == NULL)
2068 return NULL;
2069
2070 parg->tag = fmt[0];
2071 parg->pffi_type = fd->pffi_type;
2072 parg->obj = fd->setfunc(&parg->value, value, 0);
Thomas Heller86720042006-08-14 11:17:48 +00002073 if (parg->obj)
2074 return (PyObject *)parg;
2075 PyErr_Clear();
2076 Py_DECREF(parg);
2077
2078 as_parameter = PyObject_GetAttrString(value, "_as_parameter_");
2079 if (as_parameter) {
Thomas Heller5c6af802009-04-24 20:31:47 +00002080 value = PyCSimpleType_from_param(type, as_parameter);
Thomas Heller86720042006-08-14 11:17:48 +00002081 Py_DECREF(as_parameter);
2082 return value;
Thomas Hellerd4c93202006-03-08 19:35:11 +00002083 }
Thomas Heller86720042006-08-14 11:17:48 +00002084 PyErr_SetString(PyExc_TypeError,
2085 "wrong type");
2086 return NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +00002087}
2088
Thomas Heller5c6af802009-04-24 20:31:47 +00002089static PyMethodDef PyCSimpleType_methods[] = {
2090 { "from_param", PyCSimpleType_from_param, METH_O, from_param_doc },
Thomas Hellerd4c93202006-03-08 19:35:11 +00002091 { "from_address", CDataType_from_address, METH_O, from_address_doc },
Thomas Heller6ad5fbb2008-04-25 15:44:16 +00002092 { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, },
2093 { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, },
Thomas Hellerd4c93202006-03-08 19:35:11 +00002094 { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc},
2095 { NULL, NULL },
2096};
2097
Thomas Heller5c6af802009-04-24 20:31:47 +00002098PyTypeObject PyCSimpleType_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00002099 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Heller5c6af802009-04-24 20:31:47 +00002100 "_ctypes.PyCSimpleType", /* tp_name */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002101 0, /* tp_basicsize */
2102 0, /* tp_itemsize */
2103 0, /* tp_dealloc */
2104 0, /* tp_print */
2105 0, /* tp_getattr */
2106 0, /* tp_setattr */
2107 0, /* tp_compare */
2108 0, /* tp_repr */
2109 0, /* tp_as_number */
2110 &CDataType_as_sequence, /* tp_as_sequence */
2111 0, /* tp_as_mapping */
2112 0, /* tp_hash */
2113 0, /* tp_call */
2114 0, /* tp_str */
2115 0, /* tp_getattro */
2116 0, /* tp_setattro */
2117 0, /* tp_as_buffer */
2118 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
Thomas Heller5c6af802009-04-24 20:31:47 +00002119 "metatype for the PyCSimpleType Objects", /* tp_doc */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002120 0, /* tp_traverse */
2121 0, /* tp_clear */
2122 0, /* tp_richcompare */
2123 0, /* tp_weaklistoffset */
2124 0, /* tp_iter */
2125 0, /* tp_iternext */
Thomas Heller5c6af802009-04-24 20:31:47 +00002126 PyCSimpleType_methods, /* tp_methods */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002127 0, /* tp_members */
2128 0, /* tp_getset */
2129 0, /* tp_base */
2130 0, /* tp_dict */
2131 0, /* tp_descr_get */
2132 0, /* tp_descr_set */
2133 0, /* tp_dictoffset */
2134 0, /* tp_init */
2135 0, /* tp_alloc */
Thomas Heller5c6af802009-04-24 20:31:47 +00002136 PyCSimpleType_new, /* tp_new */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002137 0, /* tp_free */
2138};
2139
2140/******************************************************************/
2141/*
Thomas Heller5c6af802009-04-24 20:31:47 +00002142 PyCFuncPtrType_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +00002143 */
2144
2145static PyObject *
2146converters_from_argtypes(PyObject *ob)
2147{
2148 PyObject *converters;
Thomas Hellere81c9f62007-06-08 18:20:09 +00002149 Py_ssize_t i;
2150 Py_ssize_t nArgs;
Thomas Hellerd4c93202006-03-08 19:35:11 +00002151
2152 ob = PySequence_Tuple(ob); /* new reference */
2153 if (!ob) {
2154 PyErr_SetString(PyExc_TypeError,
2155 "_argtypes_ must be a sequence of types");
2156 return NULL;
2157 }
2158
2159 nArgs = PyTuple_GET_SIZE(ob);
2160 converters = PyTuple_New(nArgs);
2161 if (!converters)
2162 return NULL;
2163
2164 /* I have to check if this is correct. Using c_char, which has a size
2165 of 1, will be assumed to be pushed as only one byte!
2166 Aren't these promoted to integers by the C compiler and pushed as 4 bytes?
2167 */
2168
2169 for (i = 0; i < nArgs; ++i) {
2170 PyObject *tp = PyTuple_GET_ITEM(ob, i);
Thomas Hellerd4c93202006-03-08 19:35:11 +00002171 PyObject *cnv = PyObject_GetAttrString(tp, "from_param");
Thomas Heller5becdbe2006-07-06 08:48:35 +00002172 if (!cnv)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002173 goto argtypes_error_1;
2174 PyTuple_SET_ITEM(converters, i, cnv);
2175 }
2176 Py_DECREF(ob);
2177 return converters;
2178
2179 argtypes_error_1:
2180 Py_XDECREF(converters);
2181 Py_DECREF(ob);
2182 PyErr_Format(PyExc_TypeError,
Thomas Heller6088f242007-06-08 19:01:06 +00002183#if (PY_VERSION_HEX < 0x02050000)
2184 "item %d in _argtypes_ has no from_param method",
2185#else
2186 "item %zd in _argtypes_ has no from_param method",
2187#endif
2188 i+1);
Thomas Hellerd4c93202006-03-08 19:35:11 +00002189 return NULL;
2190}
2191
2192static int
2193make_funcptrtype_dict(StgDictObject *stgdict)
2194{
2195 PyObject *ob;
2196 PyObject *converters = NULL;
2197
Thomas Heller5c6af802009-04-24 20:31:47 +00002198 stgdict->align = _ctypes_get_fielddesc("P")->pffi_type->alignment;
Thomas Hellerd4c93202006-03-08 19:35:11 +00002199 stgdict->length = 1;
2200 stgdict->size = sizeof(void *);
2201 stgdict->setfunc = NULL;
2202 stgdict->getfunc = NULL;
Skip Montanaro058be9a2006-04-18 19:45:17 +00002203 stgdict->ffi_type_pointer = ffi_type_pointer;
Thomas Hellerd4c93202006-03-08 19:35:11 +00002204
2205 ob = PyDict_GetItemString((PyObject *)stgdict, "_flags_");
2206 if (!ob || !PyInt_Check(ob)) {
2207 PyErr_SetString(PyExc_TypeError,
2208 "class must define _flags_ which must be an integer");
2209 return -1;
2210 }
Thomas Hellera06a1a82008-02-13 20:21:53 +00002211 stgdict->flags = PyInt_AS_LONG(ob) | TYPEFLAG_ISPOINTER;
Thomas Hellerd4c93202006-03-08 19:35:11 +00002212
2213 /* _argtypes_ is optional... */
2214 ob = PyDict_GetItemString((PyObject *)stgdict, "_argtypes_");
2215 if (ob) {
2216 converters = converters_from_argtypes(ob);
2217 if (!converters)
2218 goto error;
2219 Py_INCREF(ob);
2220 stgdict->argtypes = ob;
2221 stgdict->converters = converters;
2222 }
2223
2224 ob = PyDict_GetItemString((PyObject *)stgdict, "_restype_");
2225 if (ob) {
2226 if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) {
2227 PyErr_SetString(PyExc_TypeError,
2228 "_restype_ must be a type, a callable, or None");
2229 return -1;
2230 }
2231 Py_INCREF(ob);
2232 stgdict->restype = ob;
2233 stgdict->checker = PyObject_GetAttrString(ob, "_check_retval_");
2234 if (stgdict->checker == NULL)
2235 PyErr_Clear();
2236 }
2237/* XXX later, maybe.
2238 ob = PyDict_GetItemString((PyObject *)stgdict, "_errcheck_");
2239 if (ob) {
2240 if (!PyCallable_Check(ob)) {
2241 PyErr_SetString(PyExc_TypeError,
2242 "_errcheck_ must be callable");
2243 return -1;
2244 }
2245 Py_INCREF(ob);
2246 stgdict->errcheck = ob;
2247 }
2248*/
2249 return 0;
2250
2251 error:
2252 Py_XDECREF(converters);
2253 return -1;
2254
2255}
2256
Thomas Heller86720042006-08-14 11:17:48 +00002257static PyCArgObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00002258PyCFuncPtrType_paramfunc(CDataObject *self)
Thomas Heller86720042006-08-14 11:17:48 +00002259{
2260 PyCArgObject *parg;
2261
Thomas Heller5c6af802009-04-24 20:31:47 +00002262 parg = PyCArgObject_new();
Thomas Heller86720042006-08-14 11:17:48 +00002263 if (parg == NULL)
2264 return NULL;
2265
2266 parg->tag = 'P';
2267 parg->pffi_type = &ffi_type_pointer;
2268 Py_INCREF(self);
2269 parg->obj = (PyObject *)self;
2270 parg->value.p = *(void **)self->b_ptr;
2271 return parg;
2272}
2273
Thomas Hellerd4c93202006-03-08 19:35:11 +00002274static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00002275PyCFuncPtrType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002276{
2277 PyTypeObject *result;
2278 StgDictObject *stgdict;
2279
2280 stgdict = (StgDictObject *)PyObject_CallObject(
Thomas Heller5c6af802009-04-24 20:31:47 +00002281 (PyObject *)&PyCStgDict_Type, NULL);
Thomas Hellerd4c93202006-03-08 19:35:11 +00002282 if (!stgdict)
2283 return NULL;
2284
Thomas Heller5c6af802009-04-24 20:31:47 +00002285 stgdict->paramfunc = PyCFuncPtrType_paramfunc;
Thomas Heller2e75c452008-06-05 17:51:15 +00002286 /* We do NOT expose the function signature in the format string. It
2287 is impossible, generally, because the only requirement for the
2288 argtypes items is that they have a .from_param method - we do not
2289 know the types of the arguments (although, in practice, most
2290 argtypes would be a ctypes type).
2291 */
Thomas Heller5c6af802009-04-24 20:31:47 +00002292 stgdict->format = _ctypes_alloc_format_string(NULL, "X{}");
Thomas Hellera06a1a82008-02-13 20:21:53 +00002293 stgdict->flags |= TYPEFLAG_ISPOINTER;
Thomas Heller86720042006-08-14 11:17:48 +00002294
Thomas Hellerd4c93202006-03-08 19:35:11 +00002295 /* create the new instance (which is a class,
2296 since we are a metatype!) */
2297 result = (PyTypeObject *)PyType_Type.tp_new(type, args, kwds);
2298 if (result == NULL) {
2299 Py_DECREF((PyObject *)stgdict);
2300 return NULL;
2301 }
2302
2303 /* replace the class dict by our updated storage dict */
2304 if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict)) {
2305 Py_DECREF(result);
2306 Py_DECREF((PyObject *)stgdict);
2307 return NULL;
2308 }
2309 Py_DECREF(result->tp_dict);
2310 result->tp_dict = (PyObject *)stgdict;
2311
2312 if (-1 == make_funcptrtype_dict(stgdict)) {
2313 Py_DECREF(result);
2314 return NULL;
2315 }
2316
2317 return (PyObject *)result;
2318}
2319
Thomas Heller5c6af802009-04-24 20:31:47 +00002320PyTypeObject PyCFuncPtrType_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00002321 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Heller5c6af802009-04-24 20:31:47 +00002322 "_ctypes.PyCFuncPtrType", /* tp_name */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002323 0, /* tp_basicsize */
2324 0, /* tp_itemsize */
2325 0, /* tp_dealloc */
2326 0, /* tp_print */
2327 0, /* tp_getattr */
2328 0, /* tp_setattr */
2329 0, /* tp_compare */
2330 0, /* tp_repr */
2331 0, /* tp_as_number */
2332 &CDataType_as_sequence, /* tp_as_sequence */
2333 0, /* tp_as_mapping */
2334 0, /* tp_hash */
2335 0, /* tp_call */
2336 0, /* tp_str */
2337 0, /* tp_getattro */
2338 0, /* tp_setattro */
2339 0, /* tp_as_buffer */
2340 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2341 "metatype for C function pointers", /* tp_doc */
2342 (traverseproc)CDataType_traverse, /* tp_traverse */
2343 (inquiry)CDataType_clear, /* tp_clear */
2344 0, /* tp_richcompare */
2345 0, /* tp_weaklistoffset */
2346 0, /* tp_iter */
2347 0, /* tp_iternext */
2348 CDataType_methods, /* tp_methods */
2349 0, /* tp_members */
2350 0, /* tp_getset */
2351 0, /* tp_base */
2352 0, /* tp_dict */
2353 0, /* tp_descr_get */
2354 0, /* tp_descr_set */
2355 0, /* tp_dictoffset */
2356 0, /* tp_init */
2357 0, /* tp_alloc */
Thomas Heller5c6af802009-04-24 20:31:47 +00002358 PyCFuncPtrType_new, /* tp_new */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002359 0, /* tp_free */
2360};
2361
2362
2363/*****************************************************************
2364 * Code to keep needed objects alive
2365 */
2366
2367static CDataObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00002368PyCData_GetContainer(CDataObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002369{
2370 while (self->b_base)
2371 self = self->b_base;
2372 if (self->b_objects == NULL) {
2373 if (self->b_length) {
2374 self->b_objects = PyDict_New();
2375 } else {
2376 Py_INCREF(Py_None);
2377 self->b_objects = Py_None;
2378 }
2379 }
2380 return self;
2381}
2382
2383static PyObject *
2384GetKeepedObjects(CDataObject *target)
2385{
Thomas Heller5c6af802009-04-24 20:31:47 +00002386 return PyCData_GetContainer(target)->b_objects;
Thomas Hellerd4c93202006-03-08 19:35:11 +00002387}
2388
2389static PyObject *
Thomas Heller45f59ab2006-06-10 19:51:46 +00002390unique_key(CDataObject *target, Py_ssize_t index)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002391{
Thomas Heller45f59ab2006-06-10 19:51:46 +00002392 char string[256];
Thomas Hellerd4c93202006-03-08 19:35:11 +00002393 char *cp = string;
Thomas Heller45f59ab2006-06-10 19:51:46 +00002394 size_t bytes_left;
2395
2396 assert(sizeof(string) - 1 > sizeof(Py_ssize_t) * 2);
2397#if (PY_VERSION_HEX < 0x02050000)
2398 cp += sprintf(cp, "%x", index);
2399#else
Thomas Heller5218ab22006-06-10 21:07:19 +00002400 cp += sprintf(cp, "%x", Py_SAFE_DOWNCAST(index, Py_ssize_t, int));
Thomas Heller45f59ab2006-06-10 19:51:46 +00002401#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +00002402 while (target->b_base) {
Thomas Heller45f59ab2006-06-10 19:51:46 +00002403 bytes_left = sizeof(string) - (cp - string) - 1;
2404 /* Hex format needs 2 characters per byte */
2405 if (bytes_left < sizeof(Py_ssize_t) * 2) {
2406 PyErr_SetString(PyExc_ValueError,
2407 "ctypes object structure too deep");
2408 return NULL;
2409 }
2410#if (PY_VERSION_HEX < 0x02050000)
2411 cp += sprintf(cp, ":%x", (int)target->b_index);
2412#else
Thomas Hellereb6dcf62006-06-10 21:17:58 +00002413 cp += sprintf(cp, ":%x", Py_SAFE_DOWNCAST(target->b_index, Py_ssize_t, int));
Thomas Heller45f59ab2006-06-10 19:51:46 +00002414#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +00002415 target = target->b_base;
2416 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +00002417 return PyString_FromStringAndSize(string, cp-string);
Thomas Hellerd4c93202006-03-08 19:35:11 +00002418}
Thomas Heller45f59ab2006-06-10 19:51:46 +00002419
Thomas Hellerd4c93202006-03-08 19:35:11 +00002420/*
Thomas Heller45f59ab2006-06-10 19:51:46 +00002421 * Keep a reference to 'keep' in the 'target', at index 'index'.
2422 *
2423 * If 'keep' is None, do nothing.
2424 *
2425 * Otherwise create a dictionary (if it does not yet exist) id the root
2426 * objects 'b_objects' item, which will store the 'keep' object under a unique
2427 * key.
2428 *
2429 * The unique_key helper travels the target's b_base pointer down to the root,
2430 * building a string containing hex-formatted indexes found during traversal,
2431 * separated by colons.
2432 *
2433 * The index tuple is used as a key into the root object's b_objects dict.
2434 *
2435 * Note: This function steals a refcount of the third argument, even if it
2436 * fails!
Thomas Hellerd4c93202006-03-08 19:35:11 +00002437 */
2438static int
Thomas Hellerfe8f8622006-03-14 19:53:09 +00002439KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002440{
2441 int result;
2442 CDataObject *ob;
2443 PyObject *key;
2444
2445/* Optimization: no need to store None */
2446 if (keep == Py_None) {
2447 Py_DECREF(Py_None);
2448 return 0;
2449 }
Thomas Heller5c6af802009-04-24 20:31:47 +00002450 ob = PyCData_GetContainer(target);
Thomas Hellerd3ed4922008-04-11 14:20:26 +00002451 if (ob->b_objects == NULL || !PyDict_CheckExact(ob->b_objects)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00002452 Py_XDECREF(ob->b_objects);
2453 ob->b_objects = keep; /* refcount consumed */
2454 return 0;
2455 }
2456 key = unique_key(target, index);
Thomas Heller45f59ab2006-06-10 19:51:46 +00002457 if (key == NULL) {
2458 Py_DECREF(keep);
2459 return -1;
2460 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00002461 result = PyDict_SetItem(ob->b_objects, key, keep);
2462 Py_DECREF(key);
2463 Py_DECREF(keep);
2464 return result;
2465}
2466
2467/******************************************************************/
2468/*
Thomas Heller5c6af802009-04-24 20:31:47 +00002469 PyCData_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +00002470 */
2471static int
Thomas Heller5c6af802009-04-24 20:31:47 +00002472PyCData_traverse(CDataObject *self, visitproc visit, void *arg)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002473{
2474 Py_VISIT(self->b_objects);
2475 Py_VISIT((PyObject *)self->b_base);
2476 return 0;
2477}
2478
2479static int
Thomas Heller5c6af802009-04-24 20:31:47 +00002480PyCData_clear(CDataObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002481{
2482 StgDictObject *dict = PyObject_stgdict((PyObject *)self);
Thomas Hellerd32e6162006-08-16 13:03:11 +00002483 assert(dict); /* Cannot be NULL for CDataObject instances */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002484 Py_CLEAR(self->b_objects);
2485 if ((self->b_needsfree)
Skip Montanaro058be9a2006-04-18 19:45:17 +00002486 && ((size_t)dict->size > sizeof(self->b_value)))
Thomas Hellerd4c93202006-03-08 19:35:11 +00002487 PyMem_Free(self->b_ptr);
2488 self->b_ptr = NULL;
2489 Py_CLEAR(self->b_base);
2490 return 0;
2491}
2492
2493static void
Thomas Heller5c6af802009-04-24 20:31:47 +00002494PyCData_dealloc(PyObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002495{
Thomas Heller5c6af802009-04-24 20:31:47 +00002496 PyCData_clear((CDataObject *)self);
Christian Heimese93237d2007-12-19 02:37:44 +00002497 Py_TYPE(self)->tp_free(self);
Thomas Hellerd4c93202006-03-08 19:35:11 +00002498}
2499
Thomas Heller5c6af802009-04-24 20:31:47 +00002500static PyMemberDef PyCData_members[] = {
Thomas Hellerd4c93202006-03-08 19:35:11 +00002501 { "_b_base_", T_OBJECT,
2502 offsetof(CDataObject, b_base), READONLY,
2503 "the base object" },
2504 { "_b_needsfree_", T_INT,
2505 offsetof(CDataObject, b_needsfree), READONLY,
2506 "whether the object owns the memory or not" },
2507 { "_objects", T_OBJECT,
2508 offsetof(CDataObject, b_objects), READONLY,
2509 "internal objects tree (NEVER CHANGE THIS OBJECT!)"},
2510 { NULL },
2511};
2512
Thomas Hellerba559362008-07-24 11:16:45 +00002513#if (PY_VERSION_HEX >= 0x02060000)
Thomas Heller5c6af802009-04-24 20:31:47 +00002514static int PyCData_NewGetBuffer(PyObject *_self, Py_buffer *view, int flags)
Thomas Heller2e75c452008-06-05 17:51:15 +00002515{
2516 CDataObject *self = (CDataObject *)_self;
2517 StgDictObject *dict = PyObject_stgdict(_self);
2518 Py_ssize_t i;
2519
2520 if (view == NULL) return 0;
Thomas Heller2e75c452008-06-05 17:51:15 +00002521
2522 view->buf = self->b_ptr;
Martin v. Löwis8401eec2008-08-14 15:56:07 +00002523 view->obj = _self;
2524 Py_INCREF(_self);
Thomas Heller2e75c452008-06-05 17:51:15 +00002525 view->len = self->b_size;
2526 view->readonly = 0;
2527 /* use default format character if not set */
2528 view->format = dict->format ? dict->format : "B";
2529 view->ndim = dict->ndim;
2530 view->shape = dict->shape;
2531 view->itemsize = self->b_size;
2532 for (i = 0; i < view->ndim; ++i) {
2533 view->itemsize /= dict->shape[i];
2534 }
2535 view->strides = NULL;
2536 view->suboffsets = NULL;
2537 view->internal = NULL;
2538 return 0;
2539}
Thomas Hellerba559362008-07-24 11:16:45 +00002540#endif
Thomas Heller2e75c452008-06-05 17:51:15 +00002541
Thomas Heller5c6af802009-04-24 20:31:47 +00002542static Py_ssize_t PyCData_GetSegcount(PyObject *_self, Py_ssize_t *lenp)
Thomas Heller2e75c452008-06-05 17:51:15 +00002543{
2544 if (lenp)
2545 *lenp = 1;
2546 return 1;
2547}
2548
Thomas Heller5c6af802009-04-24 20:31:47 +00002549static Py_ssize_t PyCData_GetBuffer(PyObject *_self, Py_ssize_t seg, void **pptr)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002550{
Thomas Hellerba29e4c2006-03-20 10:22:42 +00002551 CDataObject *self = (CDataObject *)_self;
Thomas Hellerd4c93202006-03-08 19:35:11 +00002552 if (seg != 0) {
2553 /* Hm. Must this set an exception? */
2554 return -1;
2555 }
2556 *pptr = self->b_ptr;
2557 return self->b_size;
2558}
2559
Thomas Heller5c6af802009-04-24 20:31:47 +00002560static PyBufferProcs PyCData_as_buffer = {
2561 (readbufferproc)PyCData_GetBuffer,
2562 (writebufferproc)PyCData_GetBuffer,
2563 (segcountproc)PyCData_GetSegcount,
Thomas Heller2e75c452008-06-05 17:51:15 +00002564 (charbufferproc)NULL,
Thomas Hellerba559362008-07-24 11:16:45 +00002565#if (PY_VERSION_HEX >= 0x02060000)
Thomas Heller5c6af802009-04-24 20:31:47 +00002566 (getbufferproc)PyCData_NewGetBuffer,
Thomas Heller2e75c452008-06-05 17:51:15 +00002567 (releasebufferproc)NULL,
Thomas Hellerba559362008-07-24 11:16:45 +00002568#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +00002569};
2570
2571/*
2572 * CData objects are mutable, so they cannot be hashable!
2573 */
2574static long
Thomas Heller5c6af802009-04-24 20:31:47 +00002575PyCData_nohash(PyObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002576{
2577 PyErr_SetString(PyExc_TypeError, "unhashable type");
2578 return -1;
2579}
2580
Thomas Hellera06a1a82008-02-13 20:21:53 +00002581static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00002582PyCData_reduce(PyObject *_self, PyObject *args)
Thomas Hellera06a1a82008-02-13 20:21:53 +00002583{
2584 CDataObject *self = (CDataObject *)_self;
2585
2586 if (PyObject_stgdict(_self)->flags & (TYPEFLAG_ISPOINTER|TYPEFLAG_HASPOINTER)) {
2587 PyErr_SetString(PyExc_ValueError,
2588 "ctypes objects containing pointers cannot be pickled");
2589 return NULL;
2590 }
2591 return Py_BuildValue("O(O(NN))",
2592 _unpickle,
2593 Py_TYPE(_self),
2594 PyObject_GetAttrString(_self, "__dict__"),
Gregory P. Smithdd96db62008-06-09 04:58:54 +00002595 PyString_FromStringAndSize(self->b_ptr, self->b_size));
Thomas Hellera06a1a82008-02-13 20:21:53 +00002596}
2597
2598static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00002599PyCData_setstate(PyObject *_self, PyObject *args)
Thomas Hellera06a1a82008-02-13 20:21:53 +00002600{
2601 void *data;
Thomas Hellerfffd9392008-03-25 21:18:39 +00002602 Py_ssize_t len;
Thomas Hellera06a1a82008-02-13 20:21:53 +00002603 int res;
2604 PyObject *dict, *mydict;
2605 CDataObject *self = (CDataObject *)_self;
2606 if (!PyArg_ParseTuple(args, "Os#", &dict, &data, &len))
2607 return NULL;
2608 if (len > self->b_size)
2609 len = self->b_size;
2610 memmove(self->b_ptr, data, len);
2611 mydict = PyObject_GetAttrString(_self, "__dict__");
2612 res = PyDict_Update(mydict, dict);
2613 Py_DECREF(mydict);
2614 if (res == -1)
2615 return NULL;
2616 Py_INCREF(Py_None);
2617 return Py_None;
2618}
2619
Thomas Hellerd4c93202006-03-08 19:35:11 +00002620/*
2621 * default __ctypes_from_outparam__ method returns self.
2622 */
2623static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00002624PyCData_from_outparam(PyObject *self, PyObject *args)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002625{
2626 Py_INCREF(self);
2627 return self;
2628}
2629
Thomas Heller5c6af802009-04-24 20:31:47 +00002630static PyMethodDef PyCData_methods[] = {
2631 { "__ctypes_from_outparam__", PyCData_from_outparam, METH_NOARGS, },
2632 { "__reduce__", PyCData_reduce, METH_NOARGS, },
2633 { "__setstate__", PyCData_setstate, METH_VARARGS, },
Thomas Hellerd4c93202006-03-08 19:35:11 +00002634 { NULL, NULL },
2635};
2636
Thomas Heller5c6af802009-04-24 20:31:47 +00002637PyTypeObject PyCData_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00002638 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002639 "_ctypes._CData",
2640 sizeof(CDataObject), /* tp_basicsize */
2641 0, /* tp_itemsize */
Thomas Heller5c6af802009-04-24 20:31:47 +00002642 PyCData_dealloc, /* tp_dealloc */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002643 0, /* tp_print */
2644 0, /* tp_getattr */
2645 0, /* tp_setattr */
2646 0, /* tp_compare */
2647 0, /* tp_repr */
2648 0, /* tp_as_number */
2649 0, /* tp_as_sequence */
2650 0, /* tp_as_mapping */
Thomas Heller5c6af802009-04-24 20:31:47 +00002651 PyCData_nohash, /* tp_hash */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002652 0, /* tp_call */
2653 0, /* tp_str */
2654 0, /* tp_getattro */
2655 0, /* tp_setattro */
Thomas Heller5c6af802009-04-24 20:31:47 +00002656 &PyCData_as_buffer, /* tp_as_buffer */
Thomas Heller2e75c452008-06-05 17:51:15 +00002657 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_NEWBUFFER | Py_TPFLAGS_BASETYPE, /* tp_flags */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002658 "XXX to be provided", /* tp_doc */
Thomas Heller5c6af802009-04-24 20:31:47 +00002659 (traverseproc)PyCData_traverse, /* tp_traverse */
2660 (inquiry)PyCData_clear, /* tp_clear */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002661 0, /* tp_richcompare */
2662 0, /* tp_weaklistoffset */
2663 0, /* tp_iter */
2664 0, /* tp_iternext */
Thomas Heller5c6af802009-04-24 20:31:47 +00002665 PyCData_methods, /* tp_methods */
2666 PyCData_members, /* tp_members */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002667 0, /* tp_getset */
2668 0, /* tp_base */
2669 0, /* tp_dict */
2670 0, /* tp_descr_get */
2671 0, /* tp_descr_set */
2672 0, /* tp_dictoffset */
2673 0, /* tp_init */
2674 0, /* tp_alloc */
2675 0, /* tp_new */
2676 0, /* tp_free */
2677};
2678
Thomas Heller5c6af802009-04-24 20:31:47 +00002679static int PyCData_MallocBuffer(CDataObject *obj, StgDictObject *dict)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002680{
Skip Montanaro058be9a2006-04-18 19:45:17 +00002681 if ((size_t)dict->size <= sizeof(obj->b_value)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00002682 /* No need to call malloc, can use the default buffer */
2683 obj->b_ptr = (char *)&obj->b_value;
Thomas Heller82730f82007-03-22 20:34:37 +00002684 /* The b_needsfree flag does not mean that we actually did
2685 call PyMem_Malloc to allocate the memory block; instead it
2686 means we are the *owner* of the memory and are responsible
2687 for freeing resources associated with the memory. This is
2688 also the reason that b_needsfree is exposed to Python.
2689 */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002690 obj->b_needsfree = 1;
2691 } else {
2692 /* In python 2.4, and ctypes 0.9.6, the malloc call took about
2693 33% of the creation time for c_int().
2694 */
Skip Montanaro058be9a2006-04-18 19:45:17 +00002695 obj->b_ptr = (char *)PyMem_Malloc(dict->size);
Thomas Hellere6a70392007-03-23 19:55:27 +00002696 if (obj->b_ptr == NULL) {
2697 PyErr_NoMemory();
2698 return -1;
2699 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00002700 obj->b_needsfree = 1;
2701 memset(obj->b_ptr, 0, dict->size);
2702 }
2703 obj->b_size = dict->size;
Thomas Hellere6a70392007-03-23 19:55:27 +00002704 return 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +00002705}
2706
2707PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00002708PyCData_FromBaseObj(PyObject *type, PyObject *base, Py_ssize_t index, char *adr)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002709{
2710 CDataObject *cmem;
2711 StgDictObject *dict;
2712
2713 assert(PyType_Check(type));
2714 dict = PyType_stgdict(type);
2715 if (!dict) {
2716 PyErr_SetString(PyExc_TypeError,
2717 "abstract class");
2718 return NULL;
2719 }
2720 dict->flags |= DICTFLAG_FINAL;
2721 cmem = (CDataObject *)((PyTypeObject *)type)->tp_alloc((PyTypeObject *)type, 0);
2722 if (cmem == NULL)
2723 return NULL;
2724 assert(CDataObject_Check(cmem));
2725
2726 cmem->b_length = dict->length;
2727 cmem->b_size = dict->size;
2728 if (base) { /* use base's buffer */
2729 assert(CDataObject_Check(base));
2730 cmem->b_ptr = adr;
2731 cmem->b_needsfree = 0;
2732 Py_INCREF(base);
2733 cmem->b_base = (CDataObject *)base;
2734 cmem->b_index = index;
2735 } else { /* copy contents of adr */
Thomas Heller5c6af802009-04-24 20:31:47 +00002736 if (-1 == PyCData_MallocBuffer(cmem, dict)) {
Thomas Hellere6a70392007-03-23 19:55:27 +00002737 return NULL;
2738 Py_DECREF(cmem);
2739 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00002740 memcpy(cmem->b_ptr, adr, dict->size);
2741 cmem->b_index = index;
2742 }
2743 return (PyObject *)cmem;
2744}
2745
2746/*
2747 Box a memory block into a CData instance.
2748*/
2749PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00002750PyCData_AtAddress(PyObject *type, void *buf)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002751{
2752 CDataObject *pd;
2753 StgDictObject *dict;
2754
2755 assert(PyType_Check(type));
2756 dict = PyType_stgdict(type);
2757 if (!dict) {
2758 PyErr_SetString(PyExc_TypeError,
2759 "abstract class");
2760 return NULL;
2761 }
2762 dict->flags |= DICTFLAG_FINAL;
2763
2764 pd = (CDataObject *)((PyTypeObject *)type)->tp_alloc((PyTypeObject *)type, 0);
2765 if (!pd)
2766 return NULL;
2767 assert(CDataObject_Check(pd));
Skip Montanaro058be9a2006-04-18 19:45:17 +00002768 pd->b_ptr = (char *)buf;
Thomas Hellerd4c93202006-03-08 19:35:11 +00002769 pd->b_length = dict->length;
2770 pd->b_size = dict->size;
2771 return (PyObject *)pd;
2772}
2773
2774/*
2775 This function returns TRUE for c_int, c_void_p, and these kind of
2776 classes. FALSE otherwise FALSE also for subclasses of c_int and
2777 such.
2778*/
Thomas Heller5c6af802009-04-24 20:31:47 +00002779int _ctypes_simple_instance(PyObject *obj)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002780{
2781 PyTypeObject *type = (PyTypeObject *)obj;
2782
Thomas Heller5c6af802009-04-24 20:31:47 +00002783 if (PyCSimpleTypeObject_Check(type))
Thomas Hellerd4c93202006-03-08 19:35:11 +00002784 return type->tp_base != &Simple_Type;
2785 return 0;
2786}
2787
2788PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00002789PyCData_get(PyObject *type, GETFUNC getfunc, PyObject *src,
Thomas Hellerfe8f8622006-03-14 19:53:09 +00002790 Py_ssize_t index, Py_ssize_t size, char *adr)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002791{
2792 StgDictObject *dict;
2793 if (getfunc)
2794 return getfunc(adr, size);
2795 assert(type);
2796 dict = PyType_stgdict(type);
Thomas Heller5c6af802009-04-24 20:31:47 +00002797 if (dict && dict->getfunc && !_ctypes_simple_instance(type))
Thomas Hellerd4c93202006-03-08 19:35:11 +00002798 return dict->getfunc(adr, size);
Thomas Heller5c6af802009-04-24 20:31:47 +00002799 return PyCData_FromBaseObj(type, src, index, adr);
Thomas Hellerd4c93202006-03-08 19:35:11 +00002800}
2801
2802/*
Thomas Heller5c6af802009-04-24 20:31:47 +00002803 Helper function for PyCData_set below.
Thomas Hellerd4c93202006-03-08 19:35:11 +00002804*/
2805static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00002806_PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
Thomas Hellerfe8f8622006-03-14 19:53:09 +00002807 Py_ssize_t size, char *ptr)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002808{
2809 CDataObject *src;
2810
2811 if (setfunc)
2812 return setfunc(ptr, value, size);
2813
2814 if (!CDataObject_Check(value)) {
2815 StgDictObject *dict = PyType_stgdict(type);
2816 if (dict && dict->setfunc)
2817 return dict->setfunc(ptr, value, size);
2818 /*
2819 If value is a tuple, we try to call the type with the tuple
2820 and use the result!
2821 */
2822 assert(PyType_Check(type));
2823 if (PyTuple_Check(value)) {
2824 PyObject *ob;
2825 PyObject *result;
2826 ob = PyObject_CallObject(type, value);
2827 if (ob == NULL) {
Thomas Heller5c6af802009-04-24 20:31:47 +00002828 _ctypes_extend_error(PyExc_RuntimeError, "(%s) ",
Thomas Hellerd4c93202006-03-08 19:35:11 +00002829 ((PyTypeObject *)type)->tp_name);
2830 return NULL;
2831 }
Thomas Heller5c6af802009-04-24 20:31:47 +00002832 result = _PyCData_set(dst, type, setfunc, ob,
Thomas Hellerd4c93202006-03-08 19:35:11 +00002833 size, ptr);
2834 Py_DECREF(ob);
2835 return result;
Thomas Heller5c6af802009-04-24 20:31:47 +00002836 } else if (value == Py_None && PyCPointerTypeObject_Check(type)) {
Thomas Heller76442622006-07-10 11:11:10 +00002837 *(void **)ptr = NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +00002838 Py_INCREF(Py_None);
2839 return Py_None;
2840 } else {
2841 PyErr_Format(PyExc_TypeError,
2842 "expected %s instance, got %s",
2843 ((PyTypeObject *)type)->tp_name,
Christian Heimese93237d2007-12-19 02:37:44 +00002844 Py_TYPE(value)->tp_name);
Thomas Hellerd4c93202006-03-08 19:35:11 +00002845 return NULL;
2846 }
2847 }
2848 src = (CDataObject *)value;
2849
2850 if (PyObject_IsInstance(value, type)) {
2851 memcpy(ptr,
2852 src->b_ptr,
2853 size);
2854
Thomas Heller5c6af802009-04-24 20:31:47 +00002855 if (PyCPointerTypeObject_Check(type))
Thomas Hellerd4c93202006-03-08 19:35:11 +00002856 /* XXX */;
2857
2858 value = GetKeepedObjects(src);
2859 Py_INCREF(value);
2860 return value;
2861 }
2862
Thomas Heller5c6af802009-04-24 20:31:47 +00002863 if (PyCPointerTypeObject_Check(type)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002864 && ArrayObject_Check(value)) {
2865 StgDictObject *p1, *p2;
2866 PyObject *keep;
2867 p1 = PyObject_stgdict(value);
Thomas Hellerd32e6162006-08-16 13:03:11 +00002868 assert(p1); /* Cannot be NULL for array instances */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002869 p2 = PyType_stgdict(type);
Thomas Hellerd32e6162006-08-16 13:03:11 +00002870 assert(p2); /* Cannot be NULL for pointer types */
Thomas Hellerd4c93202006-03-08 19:35:11 +00002871
2872 if (p1->proto != p2->proto) {
2873 PyErr_Format(PyExc_TypeError,
2874 "incompatible types, %s instance instead of %s instance",
Christian Heimese93237d2007-12-19 02:37:44 +00002875 Py_TYPE(value)->tp_name,
Thomas Hellerd4c93202006-03-08 19:35:11 +00002876 ((PyTypeObject *)type)->tp_name);
2877 return NULL;
2878 }
2879 *(void **)ptr = src->b_ptr;
2880
2881 keep = GetKeepedObjects(src);
2882 /*
2883 We are assigning an array object to a field which represents
2884 a pointer. This has the same effect as converting an array
2885 into a pointer. So, again, we have to keep the whole object
2886 pointed to (which is the array in this case) alive, and not
2887 only it's object list. So we create a tuple, containing
2888 b_objects list PLUS the array itself, and return that!
2889 */
Thomas Heller71dba4c2008-01-24 18:54:12 +00002890 return PyTuple_Pack(2, keep, value);
Thomas Hellerd4c93202006-03-08 19:35:11 +00002891 }
2892 PyErr_Format(PyExc_TypeError,
2893 "incompatible types, %s instance instead of %s instance",
Christian Heimese93237d2007-12-19 02:37:44 +00002894 Py_TYPE(value)->tp_name,
Thomas Hellerd4c93202006-03-08 19:35:11 +00002895 ((PyTypeObject *)type)->tp_name);
2896 return NULL;
2897}
2898
2899/*
2900 * Set a slice in object 'dst', which has the type 'type',
2901 * to the value 'value'.
2902 */
2903int
Thomas Heller5c6af802009-04-24 20:31:47 +00002904PyCData_set(PyObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value,
Thomas Hellerfe8f8622006-03-14 19:53:09 +00002905 Py_ssize_t index, Py_ssize_t size, char *ptr)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002906{
2907 CDataObject *mem = (CDataObject *)dst;
2908 PyObject *result;
2909
2910 if (!CDataObject_Check(dst)) {
2911 PyErr_SetString(PyExc_TypeError,
2912 "not a ctype instance");
2913 return -1;
2914 }
2915
Thomas Heller5c6af802009-04-24 20:31:47 +00002916 result = _PyCData_set(mem, type, setfunc, value,
Thomas Hellerd4c93202006-03-08 19:35:11 +00002917 size, ptr);
2918 if (result == NULL)
2919 return -1;
2920
2921 /* KeepRef steals a refcount from it's last argument */
2922 /* If KeepRef fails, we are stumped. The dst memory block has already
2923 been changed */
2924 return KeepRef(mem, index, result);
2925}
2926
2927
2928/******************************************************************/
2929static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00002930GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002931{
2932 CDataObject *obj;
2933 StgDictObject *dict;
2934
2935 dict = PyType_stgdict((PyObject *)type);
2936 if (!dict) {
2937 PyErr_SetString(PyExc_TypeError,
2938 "abstract class");
2939 return NULL;
2940 }
2941 dict->flags |= DICTFLAG_FINAL;
2942
2943 obj = (CDataObject *)type->tp_alloc(type, 0);
2944 if (!obj)
2945 return NULL;
2946
2947 obj->b_base = NULL;
2948 obj->b_index = 0;
2949 obj->b_objects = NULL;
2950 obj->b_length = dict->length;
2951
Thomas Heller5c6af802009-04-24 20:31:47 +00002952 if (-1 == PyCData_MallocBuffer(obj, dict)) {
Thomas Hellere6a70392007-03-23 19:55:27 +00002953 Py_DECREF(obj);
2954 return NULL;
2955 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00002956 return (PyObject *)obj;
2957}
2958/*****************************************************************/
2959/*
Thomas Heller5c6af802009-04-24 20:31:47 +00002960 PyCFuncPtr_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +00002961*/
2962
Thomas Hellerd4c93202006-03-08 19:35:11 +00002963static int
Thomas Heller5c6af802009-04-24 20:31:47 +00002964PyCFuncPtr_set_errcheck(PyCFuncPtrObject *self, PyObject *ob)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002965{
2966 if (ob && !PyCallable_Check(ob)) {
2967 PyErr_SetString(PyExc_TypeError,
2968 "the errcheck attribute must be callable");
2969 return -1;
2970 }
2971 Py_XDECREF(self->errcheck);
2972 Py_XINCREF(ob);
2973 self->errcheck = ob;
2974 return 0;
2975}
2976
2977static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00002978PyCFuncPtr_get_errcheck(PyCFuncPtrObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002979{
2980 if (self->errcheck) {
2981 Py_INCREF(self->errcheck);
2982 return self->errcheck;
2983 }
2984 Py_INCREF(Py_None);
2985 return Py_None;
2986}
2987
2988static int
Thomas Heller5c6af802009-04-24 20:31:47 +00002989PyCFuncPtr_set_restype(PyCFuncPtrObject *self, PyObject *ob)
Thomas Hellerd4c93202006-03-08 19:35:11 +00002990{
2991 if (ob == NULL) {
2992 Py_XDECREF(self->restype);
2993 self->restype = NULL;
2994 Py_XDECREF(self->checker);
2995 self->checker = NULL;
2996 return 0;
2997 }
2998 if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) {
2999 PyErr_SetString(PyExc_TypeError,
3000 "restype must be a type, a callable, or None");
3001 return -1;
3002 }
3003 Py_XDECREF(self->checker);
3004 Py_XDECREF(self->restype);
3005 Py_INCREF(ob);
3006 self->restype = ob;
3007 self->checker = PyObject_GetAttrString(ob, "_check_retval_");
3008 if (self->checker == NULL)
3009 PyErr_Clear();
3010 return 0;
3011}
3012
3013static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00003014PyCFuncPtr_get_restype(PyCFuncPtrObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003015{
3016 StgDictObject *dict;
3017 if (self->restype) {
3018 Py_INCREF(self->restype);
3019 return self->restype;
3020 }
3021 dict = PyObject_stgdict((PyObject *)self);
Thomas Heller5c6af802009-04-24 20:31:47 +00003022 assert(dict); /* Cannot be NULL for PyCFuncPtrObject instances */
Thomas Hellerd4c93202006-03-08 19:35:11 +00003023 if (dict->restype) {
3024 Py_INCREF(dict->restype);
3025 return dict->restype;
3026 } else {
3027 Py_INCREF(Py_None);
3028 return Py_None;
3029 }
3030}
3031
3032static int
Thomas Heller5c6af802009-04-24 20:31:47 +00003033PyCFuncPtr_set_argtypes(PyCFuncPtrObject *self, PyObject *ob)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003034{
3035 PyObject *converters;
3036
3037 if (ob == NULL || ob == Py_None) {
3038 Py_XDECREF(self->converters);
3039 self->converters = NULL;
3040 Py_XDECREF(self->argtypes);
3041 self->argtypes = NULL;
3042 } else {
3043 converters = converters_from_argtypes(ob);
3044 if (!converters)
3045 return -1;
3046 Py_XDECREF(self->converters);
3047 self->converters = converters;
3048 Py_XDECREF(self->argtypes);
3049 Py_INCREF(ob);
3050 self->argtypes = ob;
3051 }
3052 return 0;
3053}
3054
3055static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00003056PyCFuncPtr_get_argtypes(PyCFuncPtrObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003057{
3058 StgDictObject *dict;
3059 if (self->argtypes) {
3060 Py_INCREF(self->argtypes);
3061 return self->argtypes;
3062 }
3063 dict = PyObject_stgdict((PyObject *)self);
Thomas Heller5c6af802009-04-24 20:31:47 +00003064 assert(dict); /* Cannot be NULL for PyCFuncPtrObject instances */
Thomas Hellerd4c93202006-03-08 19:35:11 +00003065 if (dict->argtypes) {
3066 Py_INCREF(dict->argtypes);
3067 return dict->argtypes;
3068 } else {
3069 Py_INCREF(Py_None);
3070 return Py_None;
3071 }
3072}
3073
Thomas Heller5c6af802009-04-24 20:31:47 +00003074static PyGetSetDef PyCFuncPtr_getsets[] = {
3075 { "errcheck", (getter)PyCFuncPtr_get_errcheck, (setter)PyCFuncPtr_set_errcheck,
Thomas Hellerd4c93202006-03-08 19:35:11 +00003076 "a function to check for errors", NULL },
Thomas Heller5c6af802009-04-24 20:31:47 +00003077 { "restype", (getter)PyCFuncPtr_get_restype, (setter)PyCFuncPtr_set_restype,
Thomas Hellerd4c93202006-03-08 19:35:11 +00003078 "specify the result type", NULL },
Thomas Heller5c6af802009-04-24 20:31:47 +00003079 { "argtypes", (getter)PyCFuncPtr_get_argtypes,
3080 (setter)PyCFuncPtr_set_argtypes,
Thomas Hellerd4c93202006-03-08 19:35:11 +00003081 "specify the argument types", NULL },
Thomas Hellerd4c93202006-03-08 19:35:11 +00003082 { NULL, NULL }
3083};
3084
3085#ifdef MS_WIN32
3086static PPROC FindAddress(void *handle, char *name, PyObject *type)
3087{
Thomas Hellere81c9f62007-06-08 18:20:09 +00003088#ifdef MS_WIN64
3089 /* win64 has no stdcall calling conv, so it should
3090 also not have the name mangling of it.
3091 */
3092 return (PPROC)GetProcAddress(handle, name);
3093#else
Thomas Hellerd4c93202006-03-08 19:35:11 +00003094 PPROC address;
3095 char *mangled_name;
3096 int i;
Thomas Heller98619f22006-08-25 07:27:33 +00003097 StgDictObject *dict;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003098
3099 address = (PPROC)GetProcAddress(handle, name);
3100 if (address)
3101 return address;
Thomas Hellerb03cb602006-03-17 15:52:58 +00003102 if (((size_t)name & ~0xFFFF) == 0) {
3103 return NULL;
3104 }
3105
Thomas Heller98619f22006-08-25 07:27:33 +00003106 dict = PyType_stgdict((PyObject *)type);
Thomas Hellerd4c93202006-03-08 19:35:11 +00003107 /* It should not happen that dict is NULL, but better be safe */
3108 if (dict==NULL || dict->flags & FUNCFLAG_CDECL)
3109 return address;
3110
3111 /* for stdcall, try mangled names:
3112 funcname -> _funcname@<n>
3113 where n is 0, 4, 8, 12, ..., 128
3114 */
Thomas Heller59feb6f2006-03-22 12:59:53 +00003115 mangled_name = alloca(strlen(name) + 1 + 1 + 1 + 3); /* \0 _ @ %d */
Neal Norwitz93bf9022006-08-13 18:40:39 +00003116 if (!mangled_name)
3117 return NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003118 for (i = 0; i < 32; ++i) {
3119 sprintf(mangled_name, "_%s@%d", name, i*4);
3120 address = (PPROC)GetProcAddress(handle, mangled_name);
3121 if (address)
3122 return address;
3123 }
3124 return NULL;
Thomas Heller98619f22006-08-25 07:27:33 +00003125#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +00003126}
3127#endif
3128
3129/* Return 1 if usable, 0 else and exception set. */
3130static int
Thomas Hellere81c9f62007-06-08 18:20:09 +00003131_check_outarg_type(PyObject *arg, Py_ssize_t index)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003132{
3133 StgDictObject *dict;
3134
Thomas Heller5c6af802009-04-24 20:31:47 +00003135 if (PyCPointerTypeObject_Check(arg))
Thomas Hellerd4c93202006-03-08 19:35:11 +00003136 return 1;
3137
Thomas Heller5c6af802009-04-24 20:31:47 +00003138 if (PyCArrayTypeObject_Check(arg))
Thomas Hellerd4c93202006-03-08 19:35:11 +00003139 return 1;
3140
3141 dict = PyType_stgdict(arg);
3142 if (dict
3143 /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */
Gregory P. Smithdd96db62008-06-09 04:58:54 +00003144 && PyString_Check(dict->proto)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003145/* We only allow c_void_p, c_char_p and c_wchar_p as a simple output parameter type */
Gregory P. Smithdd96db62008-06-09 04:58:54 +00003146 && (strchr("PzZ", PyString_AS_STRING(dict->proto)[0]))) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00003147 return 1;
3148 }
3149
3150 PyErr_Format(PyExc_TypeError,
3151 "'out' parameter %d must be a pointer type, not %s",
Thomas Hellere81c9f62007-06-08 18:20:09 +00003152 Py_SAFE_DOWNCAST(index, Py_ssize_t, int),
Thomas Hellerd4c93202006-03-08 19:35:11 +00003153 PyType_Check(arg) ?
3154 ((PyTypeObject *)arg)->tp_name :
Christian Heimese93237d2007-12-19 02:37:44 +00003155 Py_TYPE(arg)->tp_name);
Thomas Hellerd4c93202006-03-08 19:35:11 +00003156 return 0;
3157}
3158
3159/* Returns 1 on success, 0 on error */
3160static int
3161_validate_paramflags(PyTypeObject *type, PyObject *paramflags)
3162{
Thomas Hellere81c9f62007-06-08 18:20:09 +00003163 Py_ssize_t i, len;
Thomas Hellerd32e6162006-08-16 13:03:11 +00003164 StgDictObject *dict;
3165 PyObject *argtypes;
3166
3167 dict = PyType_stgdict((PyObject *)type);
Thomas Heller5c6af802009-04-24 20:31:47 +00003168 assert(dict); /* Cannot be NULL. 'type' is a PyCFuncPtr type. */
Thomas Hellerd32e6162006-08-16 13:03:11 +00003169 argtypes = dict->argtypes;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003170
3171 if (paramflags == NULL || dict->argtypes == NULL)
3172 return 1;
3173
3174 if (!PyTuple_Check(paramflags)) {
3175 PyErr_SetString(PyExc_TypeError,
3176 "paramflags must be a tuple or None");
3177 return 0;
3178 }
3179
3180 len = PyTuple_GET_SIZE(paramflags);
3181 if (len != PyTuple_GET_SIZE(dict->argtypes)) {
3182 PyErr_SetString(PyExc_ValueError,
3183 "paramflags must have the same length as argtypes");
3184 return 0;
3185 }
3186
3187 for (i = 0; i < len; ++i) {
3188 PyObject *item = PyTuple_GET_ITEM(paramflags, i);
3189 int flag;
3190 char *name;
3191 PyObject *defval;
3192 PyObject *typ;
3193 if (!PyArg_ParseTuple(item, "i|zO", &flag, &name, &defval)) {
3194 PyErr_SetString(PyExc_TypeError,
3195 "paramflags must be a sequence of (int [,string [,value]]) tuples");
3196 return 0;
3197 }
3198 typ = PyTuple_GET_ITEM(argtypes, i);
3199 switch (flag & (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID)) {
3200 case 0:
3201 case PARAMFLAG_FIN:
3202 case PARAMFLAG_FIN | PARAMFLAG_FLCID:
3203 case PARAMFLAG_FIN | PARAMFLAG_FOUT:
3204 break;
3205 case PARAMFLAG_FOUT:
3206 if (!_check_outarg_type(typ, i+1))
3207 return 0;
3208 break;
3209 default:
3210 PyErr_Format(PyExc_TypeError,
3211 "paramflag value %d not supported",
3212 flag);
3213 return 0;
3214 }
3215 }
3216 return 1;
3217}
3218
Thomas Hellerb03cb602006-03-17 15:52:58 +00003219static int
3220_get_name(PyObject *obj, char **pname)
3221{
3222#ifdef MS_WIN32
3223 if (PyInt_Check(obj) || PyLong_Check(obj)) {
3224 /* We have to use MAKEINTRESOURCEA for Windows CE.
3225 Works on Windows as well, of course.
3226 */
3227 *pname = MAKEINTRESOURCEA(PyInt_AsUnsignedLongMask(obj) & 0xFFFF);
3228 return 1;
3229 }
3230#endif
Gregory P. Smithdd96db62008-06-09 04:58:54 +00003231 if (PyString_Check(obj) || PyUnicode_Check(obj)) {
3232 *pname = PyString_AsString(obj);
Thomas Hellere2061dc2006-03-20 08:28:19 +00003233 return *pname ? 1 : 0;
Thomas Hellerb03cb602006-03-17 15:52:58 +00003234 }
3235 PyErr_SetString(PyExc_TypeError,
3236 "function name must be string or integer");
3237 return 0;
3238}
3239
3240
Thomas Hellerd4c93202006-03-08 19:35:11 +00003241static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00003242PyCFuncPtr_FromDll(PyTypeObject *type, PyObject *args, PyObject *kwds)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003243{
3244 char *name;
3245 int (* address)(void);
3246 PyObject *dll;
3247 PyObject *obj;
Thomas Heller5c6af802009-04-24 20:31:47 +00003248 PyCFuncPtrObject *self;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003249 void *handle;
3250 PyObject *paramflags = NULL;
3251
Thomas Hellerb03cb602006-03-17 15:52:58 +00003252 if (!PyArg_ParseTuple(args, "(O&O)|O", _get_name, &name, &dll, &paramflags))
Thomas Hellerd4c93202006-03-08 19:35:11 +00003253 return NULL;
3254 if (paramflags == Py_None)
3255 paramflags = NULL;
3256
3257 obj = PyObject_GetAttrString(dll, "_handle");
3258 if (!obj)
3259 return NULL;
3260 if (!PyInt_Check(obj) && !PyLong_Check(obj)) {
3261 PyErr_SetString(PyExc_TypeError,
3262 "the _handle attribute of the second argument must be an integer");
3263 Py_DECREF(obj);
3264 return NULL;
3265 }
3266 handle = (void *)PyLong_AsVoidPtr(obj);
3267 Py_DECREF(obj);
3268 if (PyErr_Occurred()) {
3269 PyErr_SetString(PyExc_ValueError,
3270 "could not convert the _handle attribute to a pointer");
3271 return NULL;
3272 }
3273
3274#ifdef MS_WIN32
3275 address = FindAddress(handle, name, (PyObject *)type);
3276 if (!address) {
Thomas Heller59feb6f2006-03-22 12:59:53 +00003277 if (!IS_INTRESOURCE(name))
Thomas Hellerb03cb602006-03-17 15:52:58 +00003278 PyErr_Format(PyExc_AttributeError,
3279 "function '%s' not found",
3280 name);
3281 else
3282 PyErr_Format(PyExc_AttributeError,
3283 "function ordinal %d not found",
Thomas Heller59feb6f2006-03-22 12:59:53 +00003284 (WORD)(size_t)name);
Thomas Hellerd4c93202006-03-08 19:35:11 +00003285 return NULL;
3286 }
3287#else
3288 address = (PPROC)ctypes_dlsym(handle, name);
3289 if (!address) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00003290#ifdef __CYGWIN__
3291/* dlerror() isn't very helpful on cygwin */
Georg Brandl2c079292009-02-13 11:10:04 +00003292 PyErr_Format(PyExc_AttributeError,
Thomas Hellerd4c93202006-03-08 19:35:11 +00003293 "function '%s' not found (%s) ",
Georg Brandl2c079292009-02-13 11:10:04 +00003294 name);
3295#else
3296 PyErr_SetString(PyExc_AttributeError, ctypes_dlerror());
Thomas Hellerd4c93202006-03-08 19:35:11 +00003297#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +00003298 return NULL;
3299 }
3300#endif
3301 if (!_validate_paramflags(type, paramflags))
3302 return NULL;
3303
Thomas Heller5c6af802009-04-24 20:31:47 +00003304 self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds);
Thomas Hellerd4c93202006-03-08 19:35:11 +00003305 if (!self)
3306 return NULL;
3307
3308 Py_XINCREF(paramflags);
3309 self->paramflags = paramflags;
3310
3311 *(void **)self->b_ptr = address;
3312
Thomas Heller45f59ab2006-06-10 19:51:46 +00003313 Py_INCREF((PyObject *)dll); /* for KeepRef */
Thomas Hellerd4c93202006-03-08 19:35:11 +00003314 if (-1 == KeepRef((CDataObject *)self, 0, dll)) {
3315 Py_DECREF((PyObject *)self);
3316 return NULL;
3317 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00003318
3319 Py_INCREF(self);
3320 self->callable = (PyObject *)self;
3321 return (PyObject *)self;
3322}
3323
3324#ifdef MS_WIN32
3325static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00003326PyCFuncPtr_FromVtblIndex(PyTypeObject *type, PyObject *args, PyObject *kwds)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003327{
Thomas Heller5c6af802009-04-24 20:31:47 +00003328 PyCFuncPtrObject *self;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003329 int index;
3330 char *name = NULL;
3331 PyObject *paramflags = NULL;
3332 GUID *iid = NULL;
Thomas Hellerfffd9392008-03-25 21:18:39 +00003333 Py_ssize_t iid_len = 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003334
3335 if (!PyArg_ParseTuple(args, "is|Oz#", &index, &name, &paramflags, &iid, &iid_len))
3336 return NULL;
3337 if (paramflags == Py_None)
3338 paramflags = NULL;
3339
3340 if (!_validate_paramflags(type, paramflags))
3341 return NULL;
3342
Thomas Heller5c6af802009-04-24 20:31:47 +00003343 self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds);
Thomas Hellerd4c93202006-03-08 19:35:11 +00003344 self->index = index + 0x1000;
3345 Py_XINCREF(paramflags);
3346 self->paramflags = paramflags;
3347 if (iid_len == sizeof(GUID))
3348 self->iid = iid;
3349 return (PyObject *)self;
3350}
3351#endif
3352
3353/*
Thomas Heller5c6af802009-04-24 20:31:47 +00003354 PyCFuncPtr_new accepts different argument lists in addition to the standard
Thomas Hellerd4c93202006-03-08 19:35:11 +00003355 _basespec_ keyword arg:
3356
3357 one argument form
3358 "i" - function address
3359 "O" - must be a callable, creates a C callable function
3360
3361 two or more argument forms (the third argument is a paramflags tuple)
Thomas Hellerb03cb602006-03-17 15:52:58 +00003362 "(sO)|..." - (function name, dll object (with an integer handle)), paramflags
3363 "(iO)|..." - (function ordinal, dll object (with an integer handle)), paramflags
3364 "is|..." - vtable index, method name, creates callable calling COM vtbl
Thomas Hellerd4c93202006-03-08 19:35:11 +00003365*/
3366static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00003367PyCFuncPtr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003368{
Thomas Heller5c6af802009-04-24 20:31:47 +00003369 PyCFuncPtrObject *self;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003370 PyObject *callable;
3371 StgDictObject *dict;
Thomas Hellerbf027c42008-04-24 18:14:19 +00003372 CThunkObject *thunk;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003373
3374 if (PyTuple_GET_SIZE(args) == 0)
Thomas Heller5c6af802009-04-24 20:31:47 +00003375 return GenericPyCData_new(type, args, kwds);
Thomas Hellerd4c93202006-03-08 19:35:11 +00003376
Thomas Hellerb03cb602006-03-17 15:52:58 +00003377 if (1 <= PyTuple_GET_SIZE(args) && PyTuple_Check(PyTuple_GET_ITEM(args, 0)))
Thomas Heller5c6af802009-04-24 20:31:47 +00003378 return PyCFuncPtr_FromDll(type, args, kwds);
Thomas Hellerb03cb602006-03-17 15:52:58 +00003379
3380#ifdef MS_WIN32
3381 if (2 <= PyTuple_GET_SIZE(args) && PyInt_Check(PyTuple_GET_ITEM(args, 0)))
Thomas Heller5c6af802009-04-24 20:31:47 +00003382 return PyCFuncPtr_FromVtblIndex(type, args, kwds);
Thomas Hellerb03cb602006-03-17 15:52:58 +00003383#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +00003384
3385 if (1 == PyTuple_GET_SIZE(args)
3386 && (PyInt_Check(PyTuple_GET_ITEM(args, 0))
3387 || PyLong_Check(PyTuple_GET_ITEM(args, 0)))) {
3388 CDataObject *ob;
3389 void *ptr = PyLong_AsVoidPtr(PyTuple_GET_ITEM(args, 0));
Thomas Heller43617bc2008-01-11 20:29:19 +00003390 if (ptr == NULL && PyErr_Occurred())
Thomas Hellerd4c93202006-03-08 19:35:11 +00003391 return NULL;
Thomas Heller5c6af802009-04-24 20:31:47 +00003392 ob = (CDataObject *)GenericPyCData_new(type, args, kwds);
Thomas Hellerdca703f2006-08-14 07:50:14 +00003393 if (ob == NULL)
3394 return NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003395 *(void **)ob->b_ptr = ptr;
3396 return (PyObject *)ob;
3397 }
3398
3399 if (!PyArg_ParseTuple(args, "O", &callable))
3400 return NULL;
3401 if (!PyCallable_Check(callable)) {
3402 PyErr_SetString(PyExc_TypeError,
3403 "argument must be callable or integer function address");
3404 return NULL;
3405 }
3406
3407 /* XXX XXX This would allow to pass additional options. For COM
3408 method *implementations*, we would probably want different
3409 behaviour than in 'normal' callback functions: return a HRESULT if
3410 an exception occurrs in the callback, and print the traceback not
3411 only on the console, but also to OutputDebugString() or something
3412 like that.
3413 */
3414/*
3415 if (kwds && PyDict_GetItemString(kwds, "options")) {
3416 ...
3417 }
3418*/
3419
3420 dict = PyType_stgdict((PyObject *)type);
Thomas Heller5c6af802009-04-24 20:31:47 +00003421 /* XXXX Fails if we do: 'PyCFuncPtr(lambda x: x)' */
Thomas Hellerd4c93202006-03-08 19:35:11 +00003422 if (!dict || !dict->argtypes) {
3423 PyErr_SetString(PyExc_TypeError,
3424 "cannot construct instance of this class:"
3425 " no argtypes");
3426 return NULL;
3427 }
3428
Thomas Heller5c6af802009-04-24 20:31:47 +00003429 thunk = _ctypes_alloc_callback(callable,
Thomas Hellerd4c93202006-03-08 19:35:11 +00003430 dict->argtypes,
3431 dict->restype,
Thomas Hellerfbb9c0b2008-06-06 08:33:46 +00003432 dict->flags);
Thomas Hellerd4c93202006-03-08 19:35:11 +00003433 if (!thunk)
3434 return NULL;
3435
Thomas Heller5c6af802009-04-24 20:31:47 +00003436 self = (PyCFuncPtrObject *)GenericPyCData_new(type, args, kwds);
Thomas Hellerbf027c42008-04-24 18:14:19 +00003437 if (self == NULL) {
3438 Py_DECREF(thunk);
Thomas Hellerdca703f2006-08-14 07:50:14 +00003439 return NULL;
Thomas Hellerbf027c42008-04-24 18:14:19 +00003440 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00003441
3442 Py_INCREF(callable);
3443 self->callable = callable;
3444
3445 self->thunk = thunk;
Thomas Hellerbf027c42008-04-24 18:14:19 +00003446 *(void **)self->b_ptr = (void *)thunk->pcl;
3447
3448 Py_INCREF((PyObject *)thunk); /* for KeepRef */
3449 if (-1 == KeepRef((CDataObject *)self, 0, (PyObject *)thunk)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00003450 Py_DECREF((PyObject *)self);
3451 return NULL;
3452 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00003453 return (PyObject *)self;
3454}
3455
3456
3457/*
3458 _byref consumes a refcount to its argument
3459*/
3460static PyObject *
3461_byref(PyObject *obj)
3462{
3463 PyCArgObject *parg;
3464 if (!CDataObject_Check(obj)) {
3465 PyErr_SetString(PyExc_TypeError,
3466 "expected CData instance");
3467 return NULL;
3468 }
3469
Thomas Heller5c6af802009-04-24 20:31:47 +00003470 parg = PyCArgObject_new();
Thomas Hellerd4c93202006-03-08 19:35:11 +00003471 if (parg == NULL) {
3472 Py_DECREF(obj);
3473 return NULL;
3474 }
3475
3476 parg->tag = 'P';
3477 parg->pffi_type = &ffi_type_pointer;
3478 parg->obj = obj;
3479 parg->value.p = ((CDataObject *)obj)->b_ptr;
3480 return (PyObject *)parg;
3481}
3482
3483static PyObject *
3484_get_arg(int *pindex, char *name, PyObject *defval, PyObject *inargs, PyObject *kwds)
3485{
3486 PyObject *v;
3487
3488 if (*pindex < PyTuple_GET_SIZE(inargs)) {
3489 v = PyTuple_GET_ITEM(inargs, *pindex);
3490 ++*pindex;
3491 Py_INCREF(v);
3492 return v;
3493 }
3494 if (kwds && (v = PyDict_GetItemString(kwds, name))) {
3495 ++*pindex;
3496 Py_INCREF(v);
3497 return v;
3498 }
3499 if (defval) {
3500 Py_INCREF(defval);
3501 return defval;
3502 }
3503 /* we can't currently emit a better error message */
3504 if (name)
3505 PyErr_Format(PyExc_TypeError,
3506 "required argument '%s' missing", name);
3507 else
3508 PyErr_Format(PyExc_TypeError,
3509 "not enough arguments");
3510 return NULL;
3511}
3512
3513/*
3514 This function implements higher level functionality plus the ability to call
3515 functions with keyword arguments by looking at parameter flags. parameter
3516 flags is a tuple of 1, 2 or 3-tuples. The first entry in each is an integer
3517 specifying the direction of the data transfer for this parameter - 'in',
3518 'out' or 'inout' (zero means the same as 'in'). The second entry is the
3519 parameter name, and the third is the default value if the parameter is
3520 missing in the function call.
3521
3522 This function builds and returns a new tuple 'callargs' which contains the
3523 parameters to use in the call. Items on this tuple are copied from the
3524 'inargs' tuple for 'in' and 'in, out' parameters, and constructed from the
3525 'argtypes' tuple for 'out' parameters. It also calculates numretvals which
3526 is the number of return values for the function, outmask/inoutmask are
3527 bitmasks containing indexes into the callargs tuple specifying which
3528 parameters have to be returned. _build_result builds the return value of the
3529 function.
3530*/
3531static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00003532_build_callargs(PyCFuncPtrObject *self, PyObject *argtypes,
Thomas Hellerd4c93202006-03-08 19:35:11 +00003533 PyObject *inargs, PyObject *kwds,
Thomas Heller4c9dfc82006-03-16 19:26:21 +00003534 int *poutmask, int *pinoutmask, unsigned int *pnumretvals)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003535{
3536 PyObject *paramflags = self->paramflags;
3537 PyObject *callargs;
3538 StgDictObject *dict;
Thomas Hellere81c9f62007-06-08 18:20:09 +00003539 Py_ssize_t i, len;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003540 int inargs_index = 0;
3541 /* It's a little bit difficult to determine how many arguments the
3542 function call requires/accepts. For simplicity, we count the consumed
3543 args and compare this to the number of supplied args. */
Thomas Hellere81c9f62007-06-08 18:20:09 +00003544 Py_ssize_t actual_args;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003545
3546 *poutmask = 0;
3547 *pinoutmask = 0;
3548 *pnumretvals = 0;
3549
3550 /* Trivial cases, where we either return inargs itself, or a slice of it. */
3551 if (argtypes == NULL || paramflags == NULL || PyTuple_GET_SIZE(argtypes) == 0) {
3552#ifdef MS_WIN32
3553 if (self->index)
3554 return PyTuple_GetSlice(inargs, 1, PyTuple_GET_SIZE(inargs));
3555#endif
3556 Py_INCREF(inargs);
3557 return inargs;
3558 }
3559
3560 len = PyTuple_GET_SIZE(argtypes);
3561 callargs = PyTuple_New(len); /* the argument tuple we build */
3562 if (callargs == NULL)
3563 return NULL;
3564
3565#ifdef MS_WIN32
3566 /* For a COM method, skip the first arg */
3567 if (self->index) {
3568 inargs_index = 1;
3569 }
3570#endif
3571 for (i = 0; i < len; ++i) {
3572 PyObject *item = PyTuple_GET_ITEM(paramflags, i);
3573 PyObject *ob;
3574 int flag;
3575 char *name = NULL;
3576 PyObject *defval = NULL;
3577
3578 /* This way seems to be ~2 us faster than the PyArg_ParseTuple
3579 calls below. */
3580 /* We HAVE already checked that the tuple can be parsed with "i|zO", so... */
Thomas Hellere81c9f62007-06-08 18:20:09 +00003581 Py_ssize_t tsize = PyTuple_GET_SIZE(item);
Thomas Hellerd4c93202006-03-08 19:35:11 +00003582 flag = PyInt_AS_LONG(PyTuple_GET_ITEM(item, 0));
Gregory P. Smithdd96db62008-06-09 04:58:54 +00003583 name = tsize > 1 ? PyString_AS_STRING(PyTuple_GET_ITEM(item, 1)) : NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003584 defval = tsize > 2 ? PyTuple_GET_ITEM(item, 2) : NULL;
3585
3586 switch (flag & (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID)) {
3587 case PARAMFLAG_FIN | PARAMFLAG_FLCID:
Thomas Helleraa475702006-03-16 19:56:24 +00003588 /* ['in', 'lcid'] parameter. Always taken from defval,
3589 if given, else the integer 0. */
3590 if (defval == NULL) {
3591 defval = PyInt_FromLong(0);
3592 if (defval == NULL)
3593 goto error;
3594 } else
3595 Py_INCREF(defval);
Thomas Hellerd4c93202006-03-08 19:35:11 +00003596 PyTuple_SET_ITEM(callargs, i, defval);
3597 break;
3598 case (PARAMFLAG_FIN | PARAMFLAG_FOUT):
3599 *pinoutmask |= (1 << i); /* mark as inout arg */
3600 (*pnumretvals)++;
3601 /* fall through to PARAMFLAG_FIN... */
3602 case 0:
3603 case PARAMFLAG_FIN:
3604 /* 'in' parameter. Copy it from inargs. */
3605 ob =_get_arg(&inargs_index, name, defval, inargs, kwds);
3606 if (ob == NULL)
3607 goto error;
3608 PyTuple_SET_ITEM(callargs, i, ob);
3609 break;
3610 case PARAMFLAG_FOUT:
3611 /* XXX Refactor this code into a separate function. */
3612 /* 'out' parameter.
3613 argtypes[i] must be a POINTER to a c type.
3614
3615 Cannot by supplied in inargs, but a defval will be used
3616 if available. XXX Should we support getting it from kwds?
3617 */
3618 if (defval) {
3619 /* XXX Using mutable objects as defval will
3620 make the function non-threadsafe, unless we
3621 copy the object in each invocation */
3622 Py_INCREF(defval);
3623 PyTuple_SET_ITEM(callargs, i, defval);
3624 *poutmask |= (1 << i); /* mark as out arg */
3625 (*pnumretvals)++;
3626 break;
3627 }
3628 ob = PyTuple_GET_ITEM(argtypes, i);
3629 dict = PyType_stgdict(ob);
Thomas Heller0b21b432006-08-18 14:38:46 +00003630 if (dict == NULL) {
3631 /* Cannot happen: _validate_paramflags()
3632 would not accept such an object */
3633 PyErr_Format(PyExc_RuntimeError,
3634 "NULL stgdict unexpected");
3635 goto error;
3636 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +00003637 if (PyString_Check(dict->proto)) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00003638 PyErr_Format(
3639 PyExc_TypeError,
3640 "%s 'out' parameter must be passed as default value",
3641 ((PyTypeObject *)ob)->tp_name);
3642 goto error;
3643 }
Thomas Heller5c6af802009-04-24 20:31:47 +00003644 if (PyCArrayTypeObject_Check(ob))
Thomas Hellerd4c93202006-03-08 19:35:11 +00003645 ob = PyObject_CallObject(ob, NULL);
3646 else
3647 /* Create an instance of the pointed-to type */
3648 ob = PyObject_CallObject(dict->proto, NULL);
3649 /*
3650 XXX Is the following correct any longer?
3651 We must not pass a byref() to the array then but
3652 the array instance itself. Then, we cannot retrive
3653 the result from the PyCArgObject.
3654 */
3655 if (ob == NULL)
3656 goto error;
3657 /* The .from_param call that will ocurr later will pass this
3658 as a byref parameter. */
3659 PyTuple_SET_ITEM(callargs, i, ob);
3660 *poutmask |= (1 << i); /* mark as out arg */
3661 (*pnumretvals)++;
3662 break;
3663 default:
3664 PyErr_Format(PyExc_ValueError,
3665 "paramflag %d not yet implemented", flag);
3666 goto error;
3667 break;
3668 }
3669 }
3670
3671 /* We have counted the arguments we have consumed in 'inargs_index'. This
3672 must be the same as len(inargs) + len(kwds), otherwise we have
3673 either too much or not enough arguments. */
3674
3675 actual_args = PyTuple_GET_SIZE(inargs) + (kwds ? PyDict_Size(kwds) : 0);
3676 if (actual_args != inargs_index) {
3677 /* When we have default values or named parameters, this error
3678 message is misleading. See unittests/test_paramflags.py
3679 */
3680 PyErr_Format(PyExc_TypeError,
Thomas Heller6088f242007-06-08 19:01:06 +00003681#if (PY_VERSION_HEX < 0x02050000)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003682 "call takes exactly %d arguments (%d given)",
Thomas Heller6088f242007-06-08 19:01:06 +00003683#else
3684 "call takes exactly %d arguments (%zd given)",
3685#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +00003686 inargs_index, actual_args);
3687 goto error;
3688 }
3689
3690 /* outmask is a bitmask containing indexes into callargs. Items at
3691 these indexes contain values to return.
3692 */
3693 return callargs;
3694 error:
3695 Py_DECREF(callargs);
3696 return NULL;
3697}
3698
3699/* See also:
3700 http://msdn.microsoft.com/library/en-us/com/html/769127a1-1a14-4ed4-9d38-7cf3e571b661.asp
3701*/
3702/*
3703 Build return value of a function.
3704
3705 Consumes the refcount on result and callargs.
3706*/
3707static PyObject *
3708_build_result(PyObject *result, PyObject *callargs,
Thomas Heller4c9dfc82006-03-16 19:26:21 +00003709 int outmask, int inoutmask, unsigned int numretvals)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003710{
Thomas Heller4c9dfc82006-03-16 19:26:21 +00003711 unsigned int i, index;
3712 int bit;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003713 PyObject *tup = NULL;
3714
3715 if (callargs == NULL)
3716 return result;
3717 if (result == NULL || numretvals == 0) {
3718 Py_DECREF(callargs);
3719 return result;
3720 }
3721 Py_DECREF(result);
3722
Thomas Heller4c9dfc82006-03-16 19:26:21 +00003723 /* tup will not be allocated if numretvals == 1 */
Thomas Hellerd4c93202006-03-08 19:35:11 +00003724 /* allocate tuple to hold the result */
3725 if (numretvals > 1) {
3726 tup = PyTuple_New(numretvals);
3727 if (tup == NULL) {
3728 Py_DECREF(callargs);
3729 return NULL;
3730 }
3731 }
3732
3733 index = 0;
3734 for (bit = 1, i = 0; i < 32; ++i, bit <<= 1) {
3735 PyObject *v;
3736 if (bit & inoutmask) {
3737 v = PyTuple_GET_ITEM(callargs, i);
3738 Py_INCREF(v);
3739 if (numretvals == 1) {
3740 Py_DECREF(callargs);
3741 return v;
3742 }
3743 PyTuple_SET_ITEM(tup, index, v);
3744 index++;
3745 } else if (bit & outmask) {
3746 v = PyTuple_GET_ITEM(callargs, i);
3747 v = PyObject_CallMethod(v, "__ctypes_from_outparam__", NULL);
3748 if (v == NULL || numretvals == 1) {
3749 Py_DECREF(callargs);
3750 return v;
3751 }
3752 PyTuple_SET_ITEM(tup, index, v);
3753 index++;
3754 }
3755 if (index == numretvals)
3756 break;
3757 }
3758
3759 Py_DECREF(callargs);
3760 return tup;
3761}
3762
3763static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00003764PyCFuncPtr_call(PyCFuncPtrObject *self, PyObject *inargs, PyObject *kwds)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003765{
3766 PyObject *restype;
3767 PyObject *converters;
3768 PyObject *checker;
3769 PyObject *argtypes;
3770 StgDictObject *dict = PyObject_stgdict((PyObject *)self);
3771 PyObject *result;
3772 PyObject *callargs;
3773 PyObject *errcheck;
3774#ifdef MS_WIN32
3775 IUnknown *piunk = NULL;
3776#endif
3777 void *pProc = NULL;
3778
3779 int inoutmask;
3780 int outmask;
Thomas Hellerb2167612006-03-16 19:34:56 +00003781 unsigned int numretvals;
Thomas Hellerd4c93202006-03-08 19:35:11 +00003782
Thomas Heller5c6af802009-04-24 20:31:47 +00003783 assert(dict); /* Cannot be NULL for PyCFuncPtrObject instances */
Thomas Hellerd4c93202006-03-08 19:35:11 +00003784 restype = self->restype ? self->restype : dict->restype;
3785 converters = self->converters ? self->converters : dict->converters;
3786 checker = self->checker ? self->checker : dict->checker;
3787 argtypes = self->argtypes ? self->argtypes : dict->argtypes;
3788/* later, we probably want to have an errcheck field in stgdict */
3789 errcheck = self->errcheck /* ? self->errcheck : dict->errcheck */;
3790
3791
3792 pProc = *(void **)self->b_ptr;
3793#ifdef MS_WIN32
3794 if (self->index) {
3795 /* It's a COM method */
3796 CDataObject *this;
3797 this = (CDataObject *)PyTuple_GetItem(inargs, 0); /* borrowed ref! */
3798 if (!this) {
3799 PyErr_SetString(PyExc_ValueError,
3800 "native com method call without 'this' parameter");
3801 return NULL;
3802 }
3803 if (!CDataObject_Check(this)) {
3804 PyErr_SetString(PyExc_TypeError,
3805 "Expected a COM this pointer as first argument");
3806 return NULL;
3807 }
3808 /* there should be more checks? No, in Python */
3809 /* First arg is an pointer to an interface instance */
3810 if (!this->b_ptr || *(void **)this->b_ptr == NULL) {
3811 PyErr_SetString(PyExc_ValueError,
3812 "NULL COM pointer access");
3813 return NULL;
3814 }
3815 piunk = *(IUnknown **)this->b_ptr;
3816 if (NULL == piunk->lpVtbl) {
3817 PyErr_SetString(PyExc_ValueError,
3818 "COM method call without VTable");
3819 return NULL;
3820 }
3821 pProc = ((void **)piunk->lpVtbl)[self->index - 0x1000];
3822 }
3823#endif
3824 callargs = _build_callargs(self, argtypes,
3825 inargs, kwds,
3826 &outmask, &inoutmask, &numretvals);
3827 if (callargs == NULL)
3828 return NULL;
3829
3830 if (converters) {
Thomas Hellere81c9f62007-06-08 18:20:09 +00003831 int required = Py_SAFE_DOWNCAST(PyTuple_GET_SIZE(converters),
3832 Py_ssize_t, int);
3833 int actual = Py_SAFE_DOWNCAST(PyTuple_GET_SIZE(callargs),
3834 Py_ssize_t, int);
Thomas Hellerd4c93202006-03-08 19:35:11 +00003835
3836 if ((dict->flags & FUNCFLAG_CDECL) == FUNCFLAG_CDECL) {
3837 /* For cdecl functions, we allow more actual arguments
3838 than the length of the argtypes tuple.
3839 */
3840 if (required > actual) {
3841 Py_DECREF(callargs);
3842 PyErr_Format(PyExc_TypeError,
3843 "this function takes at least %d argument%s (%d given)",
3844 required,
3845 required == 1 ? "" : "s",
3846 actual);
3847 return NULL;
3848 }
3849 } else if (required != actual) {
3850 Py_DECREF(callargs);
3851 PyErr_Format(PyExc_TypeError,
3852 "this function takes %d argument%s (%d given)",
3853 required,
3854 required == 1 ? "" : "s",
3855 actual);
3856 return NULL;
3857 }
3858 }
3859
Thomas Heller5c6af802009-04-24 20:31:47 +00003860 result = _ctypes_callproc(pProc,
Thomas Hellerd4c93202006-03-08 19:35:11 +00003861 callargs,
3862#ifdef MS_WIN32
3863 piunk,
3864 self->iid,
3865#endif
3866 dict->flags,
3867 converters,
3868 restype,
3869 checker);
3870/* The 'errcheck' protocol */
3871 if (result != NULL && errcheck) {
3872 PyObject *v = PyObject_CallFunctionObjArgs(errcheck,
3873 result,
3874 self,
3875 callargs,
3876 NULL);
3877 /* If the errcheck funtion failed, return NULL.
3878 If the errcheck function returned callargs unchanged,
3879 continue normal processing.
3880 If the errcheck function returned something else,
3881 use that as result.
3882 */
3883 if (v == NULL || v != callargs) {
3884 Py_DECREF(result);
3885 Py_DECREF(callargs);
3886 return v;
3887 }
3888 Py_DECREF(v);
3889 }
3890
3891 return _build_result(result, callargs,
3892 outmask, inoutmask, numretvals);
3893}
3894
3895static int
Thomas Heller5c6af802009-04-24 20:31:47 +00003896PyCFuncPtr_traverse(PyCFuncPtrObject *self, visitproc visit, void *arg)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003897{
3898 Py_VISIT(self->callable);
3899 Py_VISIT(self->restype);
3900 Py_VISIT(self->checker);
3901 Py_VISIT(self->errcheck);
3902 Py_VISIT(self->argtypes);
3903 Py_VISIT(self->converters);
3904 Py_VISIT(self->paramflags);
Thomas Hellerbf027c42008-04-24 18:14:19 +00003905 Py_VISIT(self->thunk);
Thomas Heller5c6af802009-04-24 20:31:47 +00003906 return PyCData_traverse((CDataObject *)self, visit, arg);
Thomas Hellerd4c93202006-03-08 19:35:11 +00003907}
3908
3909static int
Thomas Heller5c6af802009-04-24 20:31:47 +00003910PyCFuncPtr_clear(PyCFuncPtrObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003911{
3912 Py_CLEAR(self->callable);
3913 Py_CLEAR(self->restype);
3914 Py_CLEAR(self->checker);
3915 Py_CLEAR(self->errcheck);
3916 Py_CLEAR(self->argtypes);
3917 Py_CLEAR(self->converters);
3918 Py_CLEAR(self->paramflags);
Thomas Hellerbf027c42008-04-24 18:14:19 +00003919 Py_CLEAR(self->thunk);
Thomas Heller5c6af802009-04-24 20:31:47 +00003920 return PyCData_clear((CDataObject *)self);
Thomas Hellerd4c93202006-03-08 19:35:11 +00003921}
3922
3923static void
Thomas Heller5c6af802009-04-24 20:31:47 +00003924PyCFuncPtr_dealloc(PyCFuncPtrObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003925{
Thomas Heller5c6af802009-04-24 20:31:47 +00003926 PyCFuncPtr_clear(self);
Christian Heimese93237d2007-12-19 02:37:44 +00003927 Py_TYPE(self)->tp_free((PyObject *)self);
Thomas Hellerd4c93202006-03-08 19:35:11 +00003928}
3929
3930static PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00003931PyCFuncPtr_repr(PyCFuncPtrObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +00003932{
3933#ifdef MS_WIN32
3934 if (self->index)
Gregory P. Smithdd96db62008-06-09 04:58:54 +00003935 return PyString_FromFormat("<COM method offset %d: %s at %p>",
Thomas Hellerd4c93202006-03-08 19:35:11 +00003936 self->index - 0x1000,
Christian Heimese93237d2007-12-19 02:37:44 +00003937 Py_TYPE(self)->tp_name,
Thomas Hellerd4c93202006-03-08 19:35:11 +00003938 self);
3939#endif
Gregory P. Smithdd96db62008-06-09 04:58:54 +00003940 return PyString_FromFormat("<%s object at %p>",
Christian Heimese93237d2007-12-19 02:37:44 +00003941 Py_TYPE(self)->tp_name,
Thomas Hellerd4c93202006-03-08 19:35:11 +00003942 self);
3943}
3944
Thomas Heller9287acf2008-05-29 19:42:34 +00003945static int
Thomas Heller5c6af802009-04-24 20:31:47 +00003946PyCFuncPtr_nonzero(PyCFuncPtrObject *self)
Thomas Heller9287acf2008-05-29 19:42:34 +00003947{
Thomas Heller0ad5ae02008-08-19 19:25:04 +00003948 return ((*(void **)self->b_ptr != NULL)
Thomas Hellerd9ccf8c2008-08-19 19:40:23 +00003949#ifdef MS_WIN32
3950 || (self->index != 0)
3951#endif
3952 );
Thomas Heller9287acf2008-05-29 19:42:34 +00003953}
3954
Thomas Heller5c6af802009-04-24 20:31:47 +00003955static PyNumberMethods PyCFuncPtr_as_number = {
Thomas Heller9287acf2008-05-29 19:42:34 +00003956 0, /* nb_add */
3957 0, /* nb_subtract */
3958 0, /* nb_multiply */
3959 0, /* nb_divide */
3960 0, /* nb_remainder */
3961 0, /* nb_divmod */
3962 0, /* nb_power */
3963 0, /* nb_negative */
3964 0, /* nb_positive */
3965 0, /* nb_absolute */
Thomas Heller5c6af802009-04-24 20:31:47 +00003966 (inquiry)PyCFuncPtr_nonzero, /* nb_nonzero */
Thomas Heller9287acf2008-05-29 19:42:34 +00003967};
3968
Thomas Heller5c6af802009-04-24 20:31:47 +00003969PyTypeObject PyCFuncPtr_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00003970 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Heller5c6af802009-04-24 20:31:47 +00003971 "_ctypes.PyCFuncPtr",
3972 sizeof(PyCFuncPtrObject), /* tp_basicsize */
Thomas Hellerd4c93202006-03-08 19:35:11 +00003973 0, /* tp_itemsize */
Thomas Heller5c6af802009-04-24 20:31:47 +00003974 (destructor)PyCFuncPtr_dealloc, /* tp_dealloc */
Thomas Hellerd4c93202006-03-08 19:35:11 +00003975 0, /* tp_print */
3976 0, /* tp_getattr */
3977 0, /* tp_setattr */
3978 0, /* tp_compare */
Thomas Heller5c6af802009-04-24 20:31:47 +00003979 (reprfunc)PyCFuncPtr_repr, /* tp_repr */
3980 &PyCFuncPtr_as_number, /* tp_as_number */
Thomas Hellerd4c93202006-03-08 19:35:11 +00003981 0, /* tp_as_sequence */
3982 0, /* tp_as_mapping */
3983 0, /* tp_hash */
Thomas Heller5c6af802009-04-24 20:31:47 +00003984 (ternaryfunc)PyCFuncPtr_call, /* tp_call */
Thomas Hellerd4c93202006-03-08 19:35:11 +00003985 0, /* tp_str */
3986 0, /* tp_getattro */
3987 0, /* tp_setattro */
Thomas Heller5c6af802009-04-24 20:31:47 +00003988 &PyCData_as_buffer, /* tp_as_buffer */
Thomas Heller2e75c452008-06-05 17:51:15 +00003989 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_NEWBUFFER | Py_TPFLAGS_BASETYPE, /* tp_flags */
Thomas Hellerd4c93202006-03-08 19:35:11 +00003990 "Function Pointer", /* tp_doc */
Thomas Heller5c6af802009-04-24 20:31:47 +00003991 (traverseproc)PyCFuncPtr_traverse, /* tp_traverse */
3992 (inquiry)PyCFuncPtr_clear, /* tp_clear */
Thomas Hellerd4c93202006-03-08 19:35:11 +00003993 0, /* tp_richcompare */
3994 0, /* tp_weaklistoffset */
3995 0, /* tp_iter */
3996 0, /* tp_iternext */
3997 0, /* tp_methods */
3998 0, /* tp_members */
Thomas Heller5c6af802009-04-24 20:31:47 +00003999 PyCFuncPtr_getsets, /* tp_getset */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004000 0, /* tp_base */
4001 0, /* tp_dict */
4002 0, /* tp_descr_get */
4003 0, /* tp_descr_set */
4004 0, /* tp_dictoffset */
4005 0, /* tp_init */
4006 0, /* tp_alloc */
Thomas Heller5c6af802009-04-24 20:31:47 +00004007 PyCFuncPtr_new, /* tp_new */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004008 0, /* tp_free */
4009};
4010
4011/*****************************************************************/
4012/*
4013 Struct_Type
4014*/
Thomas Heller7a352c02009-09-18 18:55:17 +00004015/*
4016 This function is called to initialize a Structure or Union with positional
4017 arguments. It calls itself recursively for all Structure or Union base
4018 classes, then retrieves the _fields_ member to associate the argument
4019 position with the correct field name.
4020
4021 Returns -1 on error, or the index of next argument on success.
4022 */
4023static int
4024_init_pos_args(PyObject *self, PyTypeObject *type,
4025 PyObject *args, PyObject *kwds,
4026 int index)
4027{
4028 StgDictObject *dict;
4029 PyObject *fields;
4030 int i;
4031
4032 if (PyType_stgdict((PyObject *)type->tp_base)) {
4033 index = _init_pos_args(self, type->tp_base,
4034 args, kwds,
4035 index);
4036 if (index == -1)
4037 return -1;
4038 }
4039
4040 dict = PyType_stgdict((PyObject *)type);
4041 fields = PyDict_GetItemString((PyObject *)dict, "_fields_");
4042 if (fields == NULL)
4043 return index;
4044
4045 for (i = 0;
4046 i < dict->length && (i+index) < PyTuple_GET_SIZE(args);
4047 ++i) {
4048 PyObject *pair = PySequence_GetItem(fields, i);
4049 PyObject *name, *val;
4050 int res;
4051 if (!pair)
4052 return -1;
4053 name = PySequence_GetItem(pair, 0);
4054 if (!name) {
4055 Py_DECREF(pair);
4056 return -1;
4057 }
4058 val = PyTuple_GET_ITEM(args, i + index);
4059 if (kwds && PyDict_GetItem(kwds, name)) {
4060 char *field = PyString_AsString(name);
4061 if (field == NULL) {
4062 PyErr_Clear();
4063 field = "???";
4064 }
4065 PyErr_Format(PyExc_TypeError,
4066 "duplicate values for field '%s'",
4067 field);
4068 Py_DECREF(pair);
4069 Py_DECREF(name);
4070 return -1;
4071 }
4072
4073 res = PyObject_SetAttr(self, name, val);
4074 Py_DECREF(pair);
4075 Py_DECREF(name);
4076 if (res == -1)
4077 return -1;
4078 }
4079 return index + dict->length;
4080}
4081
Thomas Hellerd4c93202006-03-08 19:35:11 +00004082static int
4083Struct_init(PyObject *self, PyObject *args, PyObject *kwds)
4084{
Thomas Hellerd4c93202006-03-08 19:35:11 +00004085/* Optimization possible: Store the attribute names _fields_[x][0]
4086 * in C accessible fields somewhere ?
4087 */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004088 if (!PyTuple_Check(args)) {
4089 PyErr_SetString(PyExc_TypeError,
4090 "args not a tuple?");
4091 return -1;
4092 }
4093 if (PyTuple_GET_SIZE(args)) {
Thomas Heller7a352c02009-09-18 18:55:17 +00004094 int res = _init_pos_args(self, Py_TYPE(self),
4095 args, kwds, 0);
4096 if (res == -1)
4097 return -1;
4098 if (res < PyTuple_GET_SIZE(args)) {
Thomas Heller415c1e32008-01-16 19:45:51 +00004099 PyErr_SetString(PyExc_TypeError,
Thomas Hellerd4c93202006-03-08 19:35:11 +00004100 "too many initializers");
4101 return -1;
4102 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00004103 }
4104
4105 if (kwds) {
4106 PyObject *key, *value;
Thomas Hellerfe8f8622006-03-14 19:53:09 +00004107 Py_ssize_t pos = 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +00004108 while(PyDict_Next(kwds, &pos, &key, &value)) {
4109 if (-1 == PyObject_SetAttr(self, key, value))
4110 return -1;
4111 }
4112 }
4113 return 0;
4114}
4115
Thomas Hellerd4c93202006-03-08 19:35:11 +00004116static PyTypeObject Struct_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00004117 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004118 "_ctypes.Structure",
4119 sizeof(CDataObject), /* tp_basicsize */
4120 0, /* tp_itemsize */
4121 0, /* tp_dealloc */
4122 0, /* tp_print */
4123 0, /* tp_getattr */
4124 0, /* tp_setattr */
4125 0, /* tp_compare */
4126 0, /* tp_repr */
4127 0, /* tp_as_number */
4128 0, /* tp_as_sequence */
4129 0, /* tp_as_mapping */
4130 0, /* tp_hash */
4131 0, /* tp_call */
4132 0, /* tp_str */
4133 0, /* tp_getattro */
4134 0, /* tp_setattro */
Thomas Heller5c6af802009-04-24 20:31:47 +00004135 &PyCData_as_buffer, /* tp_as_buffer */
Thomas Heller2e75c452008-06-05 17:51:15 +00004136 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_NEWBUFFER | Py_TPFLAGS_BASETYPE, /* tp_flags */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004137 "Structure base class", /* tp_doc */
Thomas Heller5c6af802009-04-24 20:31:47 +00004138 (traverseproc)PyCData_traverse, /* tp_traverse */
4139 (inquiry)PyCData_clear, /* tp_clear */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004140 0, /* tp_richcompare */
4141 0, /* tp_weaklistoffset */
4142 0, /* tp_iter */
4143 0, /* tp_iternext */
4144 0, /* tp_methods */
4145 0, /* tp_members */
Thomas Heller86720042006-08-14 11:17:48 +00004146 0, /* tp_getset */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004147 0, /* tp_base */
4148 0, /* tp_dict */
4149 0, /* tp_descr_get */
4150 0, /* tp_descr_set */
4151 0, /* tp_dictoffset */
4152 Struct_init, /* tp_init */
4153 0, /* tp_alloc */
Thomas Heller5c6af802009-04-24 20:31:47 +00004154 GenericPyCData_new, /* tp_new */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004155 0, /* tp_free */
4156};
4157
4158static PyTypeObject Union_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00004159 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004160 "_ctypes.Union",
4161 sizeof(CDataObject), /* tp_basicsize */
4162 0, /* tp_itemsize */
4163 0, /* tp_dealloc */
4164 0, /* tp_print */
4165 0, /* tp_getattr */
4166 0, /* tp_setattr */
4167 0, /* tp_compare */
4168 0, /* tp_repr */
4169 0, /* tp_as_number */
4170 0, /* tp_as_sequence */
4171 0, /* tp_as_mapping */
4172 0, /* tp_hash */
4173 0, /* tp_call */
4174 0, /* tp_str */
4175 0, /* tp_getattro */
4176 0, /* tp_setattro */
Thomas Heller5c6af802009-04-24 20:31:47 +00004177 &PyCData_as_buffer, /* tp_as_buffer */
Thomas Heller2e75c452008-06-05 17:51:15 +00004178 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_NEWBUFFER | Py_TPFLAGS_BASETYPE, /* tp_flags */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004179 "Union base class", /* tp_doc */
Thomas Heller5c6af802009-04-24 20:31:47 +00004180 (traverseproc)PyCData_traverse, /* tp_traverse */
4181 (inquiry)PyCData_clear, /* tp_clear */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004182 0, /* tp_richcompare */
4183 0, /* tp_weaklistoffset */
4184 0, /* tp_iter */
4185 0, /* tp_iternext */
4186 0, /* tp_methods */
4187 0, /* tp_members */
Thomas Heller86720042006-08-14 11:17:48 +00004188 0, /* tp_getset */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004189 0, /* tp_base */
4190 0, /* tp_dict */
4191 0, /* tp_descr_get */
4192 0, /* tp_descr_set */
4193 0, /* tp_dictoffset */
4194 Struct_init, /* tp_init */
4195 0, /* tp_alloc */
Thomas Heller5c6af802009-04-24 20:31:47 +00004196 GenericPyCData_new, /* tp_new */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004197 0, /* tp_free */
4198};
4199
4200
4201/******************************************************************/
4202/*
Thomas Heller5c6af802009-04-24 20:31:47 +00004203 PyCArray_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +00004204*/
4205static int
4206Array_init(CDataObject *self, PyObject *args, PyObject *kw)
4207{
Thomas Hellere81c9f62007-06-08 18:20:09 +00004208 Py_ssize_t i;
4209 Py_ssize_t n;
Thomas Hellerd4c93202006-03-08 19:35:11 +00004210
4211 if (!PyTuple_Check(args)) {
4212 PyErr_SetString(PyExc_TypeError,
4213 "args not a tuple?");
4214 return -1;
4215 }
4216 n = PyTuple_GET_SIZE(args);
4217 for (i = 0; i < n; ++i) {
4218 PyObject *v;
4219 v = PyTuple_GET_ITEM(args, i);
4220 if (-1 == PySequence_SetItem((PyObject *)self, i, v))
4221 return -1;
4222 }
4223 return 0;
4224}
4225
4226static PyObject *
Thomas Hellerbcfccca2006-03-22 13:21:16 +00004227Array_item(PyObject *_self, Py_ssize_t index)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004228{
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004229 CDataObject *self = (CDataObject *)_self;
Thomas Hellere81c9f62007-06-08 18:20:09 +00004230 Py_ssize_t offset, size;
Thomas Hellerd4c93202006-03-08 19:35:11 +00004231 StgDictObject *stgdict;
4232
Thomas Hellerce049a02006-07-14 17:51:14 +00004233
4234 if (index < 0 || index >= self->b_length) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00004235 PyErr_SetString(PyExc_IndexError,
4236 "invalid index");
4237 return NULL;
4238 }
4239
4240 stgdict = PyObject_stgdict((PyObject *)self);
Thomas Hellerd32e6162006-08-16 13:03:11 +00004241 assert(stgdict); /* Cannot be NULL for array instances */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004242 /* Would it be clearer if we got the item size from
4243 stgdict->proto's stgdict?
4244 */
4245 size = stgdict->size / stgdict->length;
4246 offset = index * size;
4247
Thomas Heller5c6af802009-04-24 20:31:47 +00004248 return PyCData_get(stgdict->proto, stgdict->getfunc, (PyObject *)self,
Thomas Hellerd4c93202006-03-08 19:35:11 +00004249 index, size, self->b_ptr + offset);
4250}
4251
4252static PyObject *
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004253Array_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004254{
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004255 CDataObject *self = (CDataObject *)_self;
Thomas Hellerd4c93202006-03-08 19:35:11 +00004256 StgDictObject *stgdict, *itemdict;
4257 PyObject *proto;
4258 PyListObject *np;
Thomas Hellerfe8f8622006-03-14 19:53:09 +00004259 Py_ssize_t i, len;
Thomas Hellerd4c93202006-03-08 19:35:11 +00004260
4261 if (ilow < 0)
4262 ilow = 0;
Thomas Hellerce049a02006-07-14 17:51:14 +00004263 else if (ilow > self->b_length)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004264 ilow = self->b_length;
4265 if (ihigh < ilow)
4266 ihigh = ilow;
Thomas Hellerce049a02006-07-14 17:51:14 +00004267 else if (ihigh > self->b_length)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004268 ihigh = self->b_length;
4269 len = ihigh - ilow;
4270
4271 stgdict = PyObject_stgdict((PyObject *)self);
Thomas Hellerd32e6162006-08-16 13:03:11 +00004272 assert(stgdict); /* Cannot be NULL for array object instances */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004273 proto = stgdict->proto;
4274 itemdict = PyType_stgdict(proto);
Thomas Heller0b21b432006-08-18 14:38:46 +00004275 assert(itemdict); /* proto is the item type of the array, a ctypes
4276 type, so this cannot be NULL */
Thomas Heller5c6af802009-04-24 20:31:47 +00004277 if (itemdict->getfunc == _ctypes_get_fielddesc("c")->getfunc) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00004278 char *ptr = (char *)self->b_ptr;
Gregory P. Smithdd96db62008-06-09 04:58:54 +00004279 return PyString_FromStringAndSize(ptr + ilow, len);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004280#ifdef CTYPES_UNICODE
Thomas Heller5c6af802009-04-24 20:31:47 +00004281 } else if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00004282 wchar_t *ptr = (wchar_t *)self->b_ptr;
4283 return PyUnicode_FromWideChar(ptr + ilow, len);
4284#endif
4285 }
4286
4287 np = (PyListObject *) PyList_New(len);
4288 if (np == NULL)
4289 return NULL;
4290
4291 for (i = 0; i < len; i++) {
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004292 PyObject *v = Array_item(_self, i+ilow);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004293 PyList_SET_ITEM(np, i, v);
4294 }
4295 return (PyObject *)np;
4296}
4297
Thomas Woutersdcb3c382007-08-30 21:01:17 +00004298static PyObject *
4299Array_subscript(PyObject *_self, PyObject *item)
4300{
4301 CDataObject *self = (CDataObject *)_self;
4302
4303 if (PyIndex_Check(item)) {
4304 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
4305
4306 if (i == -1 && PyErr_Occurred())
4307 return NULL;
4308 if (i < 0)
4309 i += self->b_length;
4310 return Array_item(_self, i);
4311 }
4312 else if PySlice_Check(item) {
4313 StgDictObject *stgdict, *itemdict;
4314 PyObject *proto;
4315 PyObject *np;
4316 Py_ssize_t start, stop, step, slicelen, cur, i;
4317
4318 if (PySlice_GetIndicesEx((PySliceObject *)item,
4319 self->b_length, &start, &stop,
4320 &step, &slicelen) < 0) {
4321 return NULL;
4322 }
4323
4324 stgdict = PyObject_stgdict((PyObject *)self);
4325 assert(stgdict); /* Cannot be NULL for array object instances */
4326 proto = stgdict->proto;
4327 itemdict = PyType_stgdict(proto);
4328 assert(itemdict); /* proto is the item type of the array, a
4329 ctypes type, so this cannot be NULL */
4330
Thomas Heller5c6af802009-04-24 20:31:47 +00004331 if (itemdict->getfunc == _ctypes_get_fielddesc("c")->getfunc) {
Thomas Woutersdcb3c382007-08-30 21:01:17 +00004332 char *ptr = (char *)self->b_ptr;
4333 char *dest;
4334
4335 if (slicelen <= 0)
Gregory P. Smithdd96db62008-06-09 04:58:54 +00004336 return PyString_FromString("");
Thomas Woutersdcb3c382007-08-30 21:01:17 +00004337 if (step == 1) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +00004338 return PyString_FromStringAndSize(ptr + start,
Thomas Woutersdcb3c382007-08-30 21:01:17 +00004339 slicelen);
4340 }
4341 dest = (char *)PyMem_Malloc(slicelen);
4342
4343 if (dest == NULL)
4344 return PyErr_NoMemory();
4345
4346 for (cur = start, i = 0; i < slicelen;
4347 cur += step, i++) {
4348 dest[i] = ptr[cur];
4349 }
4350
Gregory P. Smithdd96db62008-06-09 04:58:54 +00004351 np = PyString_FromStringAndSize(dest, slicelen);
Thomas Woutersdcb3c382007-08-30 21:01:17 +00004352 PyMem_Free(dest);
4353 return np;
4354 }
4355#ifdef CTYPES_UNICODE
Thomas Heller5c6af802009-04-24 20:31:47 +00004356 if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) {
Thomas Woutersdcb3c382007-08-30 21:01:17 +00004357 wchar_t *ptr = (wchar_t *)self->b_ptr;
4358 wchar_t *dest;
4359
4360 if (slicelen <= 0)
4361 return PyUnicode_FromUnicode(NULL, 0);
4362 if (step == 1) {
4363 return PyUnicode_FromWideChar(ptr + start,
4364 slicelen);
4365 }
4366
4367 dest = (wchar_t *)PyMem_Malloc(
4368 slicelen * sizeof(wchar_t));
4369
4370 for (cur = start, i = 0; i < slicelen;
4371 cur += step, i++) {
4372 dest[i] = ptr[cur];
4373 }
4374
4375 np = PyUnicode_FromWideChar(dest, slicelen);
4376 PyMem_Free(dest);
4377 return np;
4378 }
4379#endif
4380
4381 np = PyList_New(slicelen);
4382 if (np == NULL)
4383 return NULL;
4384
4385 for (cur = start, i = 0; i < slicelen;
4386 cur += step, i++) {
4387 PyObject *v = Array_item(_self, cur);
4388 PyList_SET_ITEM(np, i, v);
4389 }
4390 return np;
4391 }
4392 else {
4393 PyErr_SetString(PyExc_TypeError,
4394 "indices must be integers");
4395 return NULL;
4396 }
4397
4398}
4399
Thomas Hellerd4c93202006-03-08 19:35:11 +00004400static int
Thomas Hellerbcfccca2006-03-22 13:21:16 +00004401Array_ass_item(PyObject *_self, Py_ssize_t index, PyObject *value)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004402{
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004403 CDataObject *self = (CDataObject *)_self;
Thomas Hellere81c9f62007-06-08 18:20:09 +00004404 Py_ssize_t size, offset;
Thomas Hellerd4c93202006-03-08 19:35:11 +00004405 StgDictObject *stgdict;
4406 char *ptr;
4407
4408 if (value == NULL) {
4409 PyErr_SetString(PyExc_TypeError,
4410 "Array does not support item deletion");
4411 return -1;
4412 }
4413
4414 stgdict = PyObject_stgdict((PyObject *)self);
Thomas Hellerd32e6162006-08-16 13:03:11 +00004415 assert(stgdict); /* Cannot be NULL for array object instances */
Thomas Hellerce049a02006-07-14 17:51:14 +00004416 if (index < 0 || index >= stgdict->length) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00004417 PyErr_SetString(PyExc_IndexError,
4418 "invalid index");
4419 return -1;
4420 }
4421 size = stgdict->size / stgdict->length;
4422 offset = index * size;
4423 ptr = self->b_ptr + offset;
4424
Thomas Heller5c6af802009-04-24 20:31:47 +00004425 return PyCData_set((PyObject *)self, stgdict->proto, stgdict->setfunc, value,
Thomas Hellerd4c93202006-03-08 19:35:11 +00004426 index, size, ptr);
4427}
4428
4429static int
Thomas Hellerbcfccca2006-03-22 13:21:16 +00004430Array_ass_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *value)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004431{
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004432 CDataObject *self = (CDataObject *)_self;
Thomas Hellere81c9f62007-06-08 18:20:09 +00004433 Py_ssize_t i, len;
Thomas Hellerd4c93202006-03-08 19:35:11 +00004434
4435 if (value == NULL) {
4436 PyErr_SetString(PyExc_TypeError,
4437 "Array does not support item deletion");
4438 return -1;
4439 }
4440
4441 if (ilow < 0)
4442 ilow = 0;
Thomas Hellerce049a02006-07-14 17:51:14 +00004443 else if (ilow > self->b_length)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004444 ilow = self->b_length;
4445 if (ihigh < 0)
4446 ihigh = 0;
4447 if (ihigh < ilow)
4448 ihigh = ilow;
Thomas Hellerce049a02006-07-14 17:51:14 +00004449 else if (ihigh > self->b_length)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004450 ihigh = self->b_length;
4451
4452 len = PySequence_Length(value);
Thomas Hellerce049a02006-07-14 17:51:14 +00004453 if (len != ihigh - ilow) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00004454 PyErr_SetString(PyExc_ValueError,
4455 "Can only assign sequence of same size");
4456 return -1;
4457 }
4458 for (i = 0; i < len; i++) {
4459 PyObject *item = PySequence_GetItem(value, i);
4460 int result;
4461 if (item == NULL)
4462 return -1;
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004463 result = Array_ass_item(_self, i+ilow, item);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004464 Py_DECREF(item);
4465 if (result == -1)
4466 return -1;
4467 }
4468 return 0;
4469}
4470
Thomas Woutersdcb3c382007-08-30 21:01:17 +00004471static int
4472Array_ass_subscript(PyObject *_self, PyObject *item, PyObject *value)
4473{
4474 CDataObject *self = (CDataObject *)_self;
4475
4476 if (value == NULL) {
4477 PyErr_SetString(PyExc_TypeError,
4478 "Array does not support item deletion");
4479 return -1;
4480 }
4481
4482 if (PyIndex_Check(item)) {
4483 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
4484
4485 if (i == -1 && PyErr_Occurred())
4486 return -1;
4487 if (i < 0)
4488 i += self->b_length;
4489 return Array_ass_item(_self, i, value);
4490 }
4491 else if (PySlice_Check(item)) {
4492 Py_ssize_t start, stop, step, slicelen, otherlen, i, cur;
4493
4494 if (PySlice_GetIndicesEx((PySliceObject *)item,
4495 self->b_length, &start, &stop,
4496 &step, &slicelen) < 0) {
4497 return -1;
4498 }
4499 if ((step < 0 && start < stop) ||
4500 (step > 0 && start > stop))
4501 stop = start;
4502
4503 otherlen = PySequence_Length(value);
4504 if (otherlen != slicelen) {
4505 PyErr_SetString(PyExc_ValueError,
4506 "Can only assign sequence of same size");
4507 return -1;
4508 }
4509 for (cur = start, i = 0; i < otherlen; cur += step, i++) {
4510 PyObject *item = PySequence_GetItem(value, i);
4511 int result;
4512 if (item == NULL)
4513 return -1;
4514 result = Array_ass_item(_self, cur, item);
4515 Py_DECREF(item);
4516 if (result == -1)
4517 return -1;
4518 }
4519 return 0;
4520 }
4521 else {
4522 PyErr_SetString(PyExc_TypeError,
4523 "indices must be integer");
4524 return -1;
4525 }
4526}
4527
Thomas Hellerbcfccca2006-03-22 13:21:16 +00004528static Py_ssize_t
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004529Array_length(PyObject *_self)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004530{
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004531 CDataObject *self = (CDataObject *)_self;
Thomas Hellerd4c93202006-03-08 19:35:11 +00004532 return self->b_length;
4533}
4534
4535static PySequenceMethods Array_as_sequence = {
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004536 Array_length, /* sq_length; */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004537 0, /* sq_concat; */
4538 0, /* sq_repeat; */
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004539 Array_item, /* sq_item; */
4540 Array_slice, /* sq_slice; */
4541 Array_ass_item, /* sq_ass_item; */
4542 Array_ass_slice, /* sq_ass_slice; */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004543 0, /* sq_contains; */
4544
4545 0, /* sq_inplace_concat; */
4546 0, /* sq_inplace_repeat; */
4547};
4548
Thomas Woutersdcb3c382007-08-30 21:01:17 +00004549static PyMappingMethods Array_as_mapping = {
4550 Array_length,
4551 Array_subscript,
4552 Array_ass_subscript,
4553};
4554
Thomas Heller5c6af802009-04-24 20:31:47 +00004555PyTypeObject PyCArray_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00004556 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004557 "_ctypes.Array",
4558 sizeof(CDataObject), /* tp_basicsize */
4559 0, /* tp_itemsize */
4560 0, /* tp_dealloc */
4561 0, /* tp_print */
4562 0, /* tp_getattr */
4563 0, /* tp_setattr */
4564 0, /* tp_compare */
4565 0, /* tp_repr */
4566 0, /* tp_as_number */
4567 &Array_as_sequence, /* tp_as_sequence */
Thomas Woutersdcb3c382007-08-30 21:01:17 +00004568 &Array_as_mapping, /* tp_as_mapping */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004569 0, /* tp_hash */
4570 0, /* tp_call */
4571 0, /* tp_str */
4572 0, /* tp_getattro */
4573 0, /* tp_setattro */
Thomas Heller5c6af802009-04-24 20:31:47 +00004574 &PyCData_as_buffer, /* tp_as_buffer */
Thomas Heller2e75c452008-06-05 17:51:15 +00004575 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_NEWBUFFER | Py_TPFLAGS_BASETYPE, /* tp_flags */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004576 "XXX to be provided", /* tp_doc */
Thomas Heller5c6af802009-04-24 20:31:47 +00004577 (traverseproc)PyCData_traverse, /* tp_traverse */
4578 (inquiry)PyCData_clear, /* tp_clear */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004579 0, /* tp_richcompare */
4580 0, /* tp_weaklistoffset */
4581 0, /* tp_iter */
4582 0, /* tp_iternext */
4583 0, /* tp_methods */
4584 0, /* tp_members */
Thomas Heller86720042006-08-14 11:17:48 +00004585 0, /* tp_getset */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004586 0, /* tp_base */
4587 0, /* tp_dict */
4588 0, /* tp_descr_get */
4589 0, /* tp_descr_set */
4590 0, /* tp_dictoffset */
4591 (initproc)Array_init, /* tp_init */
4592 0, /* tp_alloc */
Thomas Heller5c6af802009-04-24 20:31:47 +00004593 GenericPyCData_new, /* tp_new */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004594 0, /* tp_free */
4595};
4596
4597PyObject *
Thomas Heller5c6af802009-04-24 20:31:47 +00004598PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004599{
Thomas Hellere4c03e42008-01-24 18:36:27 +00004600 static PyObject *cache;
Thomas Hellerd4c93202006-03-08 19:35:11 +00004601 PyObject *key;
4602 PyObject *result;
4603 char name[256];
Thomas Heller71dba4c2008-01-24 18:54:12 +00004604 PyObject *len;
Thomas Hellerd4c93202006-03-08 19:35:11 +00004605
Thomas Hellere4c03e42008-01-24 18:36:27 +00004606 if (cache == NULL) {
4607 cache = PyDict_New();
4608 if (cache == NULL)
4609 return NULL;
4610 }
Thomas Heller71dba4c2008-01-24 18:54:12 +00004611 len = PyInt_FromSsize_t(length);
4612 if (len == NULL)
4613 return NULL;
4614 key = PyTuple_Pack(2, itemtype, len);
4615 Py_DECREF(len);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004616 if (!key)
4617 return NULL;
Thomas Hellere4c03e42008-01-24 18:36:27 +00004618 result = PyDict_GetItemProxy(cache, key);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004619 if (result) {
Thomas Hellere4c03e42008-01-24 18:36:27 +00004620 Py_INCREF(result);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004621 Py_DECREF(key);
4622 return result;
Thomas Hellere4c03e42008-01-24 18:36:27 +00004623 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00004624
4625 if (!PyType_Check(itemtype)) {
4626 PyErr_SetString(PyExc_TypeError,
4627 "Expected a type object");
4628 return NULL;
4629 }
Thomas Hellerfe8f8622006-03-14 19:53:09 +00004630#ifdef MS_WIN64
4631 sprintf(name, "%.200s_Array_%Id",
Thomas Hellerd4c93202006-03-08 19:35:11 +00004632 ((PyTypeObject *)itemtype)->tp_name, length);
Thomas Hellerfe8f8622006-03-14 19:53:09 +00004633#else
4634 sprintf(name, "%.200s_Array_%ld",
4635 ((PyTypeObject *)itemtype)->tp_name, (long)length);
4636#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +00004637
Thomas Heller5c6af802009-04-24 20:31:47 +00004638 result = PyObject_CallFunction((PyObject *)&PyCArrayType_Type,
Thomas Heller9998f782006-03-15 21:49:52 +00004639#if (PY_VERSION_HEX < 0x02050000)
4640 "s(O){s:i,s:O}",
4641#else
Thomas Hellerfe8f8622006-03-14 19:53:09 +00004642 "s(O){s:n,s:O}",
Thomas Heller9998f782006-03-15 21:49:52 +00004643#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +00004644 name,
Thomas Heller5c6af802009-04-24 20:31:47 +00004645 &PyCArray_Type,
Thomas Hellerd4c93202006-03-08 19:35:11 +00004646 "_length_",
4647 length,
4648 "_type_",
4649 itemtype
4650 );
Thomas Heller71dba4c2008-01-24 18:54:12 +00004651 if (result == NULL) {
4652 Py_DECREF(key);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004653 return NULL;
Thomas Heller71dba4c2008-01-24 18:54:12 +00004654 }
Thomas Hellere4c03e42008-01-24 18:36:27 +00004655 if (-1 == PyDict_SetItemProxy(cache, key, result)) {
Thomas Heller902d3072008-01-16 19:16:27 +00004656 Py_DECREF(key);
4657 Py_DECREF(result);
4658 return NULL;
4659 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00004660 Py_DECREF(key);
4661 return result;
4662}
4663
4664
4665/******************************************************************/
4666/*
4667 Simple_Type
4668*/
4669
4670static int
4671Simple_set_value(CDataObject *self, PyObject *value)
4672{
4673 PyObject *result;
4674 StgDictObject *dict = PyObject_stgdict((PyObject *)self);
4675
Thomas Heller153038e2007-12-18 19:00:34 +00004676 if (value == NULL) {
4677 PyErr_SetString(PyExc_TypeError,
4678 "can't delete attribute");
4679 return -1;
4680 }
Thomas Hellerd32e6162006-08-16 13:03:11 +00004681 assert(dict); /* Cannot be NULL for CDataObject instances */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004682 assert(dict->setfunc);
4683 result = dict->setfunc(self->b_ptr, value, dict->size);
4684 if (!result)
4685 return -1;
4686
4687 /* consumes the refcount the setfunc returns */
4688 return KeepRef(self, 0, result);
4689}
4690
4691static int
4692Simple_init(CDataObject *self, PyObject *args, PyObject *kw)
4693{
4694 PyObject *value = NULL;
4695 if (!PyArg_UnpackTuple(args, "__init__", 0, 1, &value))
4696 return -1;
4697 if (value)
4698 return Simple_set_value(self, value);
4699 return 0;
4700}
4701
4702static PyObject *
4703Simple_get_value(CDataObject *self)
4704{
4705 StgDictObject *dict;
4706 dict = PyObject_stgdict((PyObject *)self);
Thomas Hellerd32e6162006-08-16 13:03:11 +00004707 assert(dict); /* Cannot be NULL for CDataObject instances */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004708 assert(dict->getfunc);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004709 return dict->getfunc(self->b_ptr, self->b_size);
4710}
4711
Thomas Hellerd4c93202006-03-08 19:35:11 +00004712static PyGetSetDef Simple_getsets[] = {
4713 { "value", (getter)Simple_get_value, (setter)Simple_set_value,
4714 "current value", NULL },
Thomas Hellerd4c93202006-03-08 19:35:11 +00004715 { NULL, NULL }
4716};
4717
4718static PyObject *
4719Simple_from_outparm(PyObject *self, PyObject *args)
4720{
Thomas Heller5c6af802009-04-24 20:31:47 +00004721 if (_ctypes_simple_instance((PyObject *)Py_TYPE(self))) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00004722 Py_INCREF(self);
4723 return self;
4724 }
4725 /* call stgdict->getfunc */
4726 return Simple_get_value((CDataObject *)self);
4727}
4728
4729static PyMethodDef Simple_methods[] = {
4730 { "__ctypes_from_outparam__", Simple_from_outparm, METH_NOARGS, },
4731 { NULL, NULL },
4732};
4733
4734static int Simple_nonzero(CDataObject *self)
4735{
4736 return memcmp(self->b_ptr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", self->b_size);
4737}
4738
4739static PyNumberMethods Simple_as_number = {
4740 0, /* nb_add */
4741 0, /* nb_subtract */
4742 0, /* nb_multiply */
4743 0, /* nb_divide */
4744 0, /* nb_remainder */
4745 0, /* nb_divmod */
4746 0, /* nb_power */
4747 0, /* nb_negative */
4748 0, /* nb_positive */
4749 0, /* nb_absolute */
4750 (inquiry)Simple_nonzero, /* nb_nonzero */
4751};
4752
Thomas Hellerd4c93202006-03-08 19:35:11 +00004753/* "%s(%s)" % (self.__class__.__name__, self.value) */
4754static PyObject *
4755Simple_repr(CDataObject *self)
4756{
4757 PyObject *val, *name, *args, *result;
4758 static PyObject *format;
4759
Christian Heimese93237d2007-12-19 02:37:44 +00004760 if (Py_TYPE(self)->tp_base != &Simple_Type) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +00004761 return PyString_FromFormat("<%s object at %p>",
Christian Heimese93237d2007-12-19 02:37:44 +00004762 Py_TYPE(self)->tp_name, self);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004763 }
4764
4765 if (format == NULL) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +00004766 format = PyString_InternFromString("%s(%r)");
Thomas Hellerd4c93202006-03-08 19:35:11 +00004767 if (format == NULL)
4768 return NULL;
4769 }
4770
4771 val = Simple_get_value(self);
4772 if (val == NULL)
4773 return NULL;
4774
Gregory P. Smithdd96db62008-06-09 04:58:54 +00004775 name = PyString_FromString(Py_TYPE(self)->tp_name);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004776 if (name == NULL) {
Thomas Hellerfe8f8622006-03-14 19:53:09 +00004777 Py_DECREF(val);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004778 return NULL;
4779 }
4780
4781 args = PyTuple_Pack(2, name, val);
4782 Py_DECREF(name);
4783 Py_DECREF(val);
4784 if (args == NULL)
4785 return NULL;
4786
Gregory P. Smithdd96db62008-06-09 04:58:54 +00004787 result = PyString_Format(format, args);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004788 Py_DECREF(args);
4789 return result;
4790}
4791
4792static PyTypeObject Simple_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00004793 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004794 "_ctypes._SimpleCData",
4795 sizeof(CDataObject), /* tp_basicsize */
4796 0, /* tp_itemsize */
4797 0, /* tp_dealloc */
4798 0, /* tp_print */
4799 0, /* tp_getattr */
4800 0, /* tp_setattr */
4801 0, /* tp_compare */
4802 (reprfunc)&Simple_repr, /* tp_repr */
4803 &Simple_as_number, /* tp_as_number */
4804 0, /* tp_as_sequence */
4805 0, /* tp_as_mapping */
4806 0, /* tp_hash */
4807 0, /* tp_call */
4808 0, /* tp_str */
4809 0, /* tp_getattro */
4810 0, /* tp_setattro */
Thomas Heller5c6af802009-04-24 20:31:47 +00004811 &PyCData_as_buffer, /* tp_as_buffer */
Thomas Heller2e75c452008-06-05 17:51:15 +00004812 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_NEWBUFFER | Py_TPFLAGS_BASETYPE, /* tp_flags */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004813 "XXX to be provided", /* tp_doc */
Thomas Heller5c6af802009-04-24 20:31:47 +00004814 (traverseproc)PyCData_traverse, /* tp_traverse */
4815 (inquiry)PyCData_clear, /* tp_clear */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004816 0, /* tp_richcompare */
4817 0, /* tp_weaklistoffset */
4818 0, /* tp_iter */
4819 0, /* tp_iternext */
4820 Simple_methods, /* tp_methods */
4821 0, /* tp_members */
4822 Simple_getsets, /* tp_getset */
4823 0, /* tp_base */
4824 0, /* tp_dict */
4825 0, /* tp_descr_get */
4826 0, /* tp_descr_set */
4827 0, /* tp_dictoffset */
4828 (initproc)Simple_init, /* tp_init */
4829 0, /* tp_alloc */
Thomas Heller5c6af802009-04-24 20:31:47 +00004830 GenericPyCData_new, /* tp_new */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004831 0, /* tp_free */
4832};
4833
4834/******************************************************************/
4835/*
Thomas Heller5c6af802009-04-24 20:31:47 +00004836 PyCPointer_Type
Thomas Hellerd4c93202006-03-08 19:35:11 +00004837*/
4838static PyObject *
Thomas Hellerbcfccca2006-03-22 13:21:16 +00004839Pointer_item(PyObject *_self, Py_ssize_t index)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004840{
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004841 CDataObject *self = (CDataObject *)_self;
Thomas Hellere81c9f62007-06-08 18:20:09 +00004842 Py_ssize_t size;
Thomas Heller45f59ab2006-06-10 19:51:46 +00004843 Py_ssize_t offset;
Thomas Hellerd4c93202006-03-08 19:35:11 +00004844 StgDictObject *stgdict, *itemdict;
4845 PyObject *proto;
4846
4847 if (*(void **)self->b_ptr == NULL) {
4848 PyErr_SetString(PyExc_ValueError,
4849 "NULL pointer access");
4850 return NULL;
4851 }
4852
Thomas Hellerd4c93202006-03-08 19:35:11 +00004853 stgdict = PyObject_stgdict((PyObject *)self);
Thomas Hellerd32e6162006-08-16 13:03:11 +00004854 assert(stgdict); /* Cannot be NULL for pointer object instances */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004855
4856 proto = stgdict->proto;
Thomas Hellerd32e6162006-08-16 13:03:11 +00004857 assert(proto);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004858 itemdict = PyType_stgdict(proto);
Thomas Heller0b21b432006-08-18 14:38:46 +00004859 assert(itemdict); /* proto is the item type of the pointer, a ctypes
4860 type, so this cannot be NULL */
4861
Thomas Hellerd4c93202006-03-08 19:35:11 +00004862 size = itemdict->size;
4863 offset = index * itemdict->size;
4864
Thomas Heller5c6af802009-04-24 20:31:47 +00004865 return PyCData_get(proto, stgdict->getfunc, (PyObject *)self,
Thomas Hellerd4c93202006-03-08 19:35:11 +00004866 index, size, (*(char **)self->b_ptr) + offset);
4867}
4868
4869static int
Thomas Hellerbcfccca2006-03-22 13:21:16 +00004870Pointer_ass_item(PyObject *_self, Py_ssize_t index, PyObject *value)
Thomas Hellerd4c93202006-03-08 19:35:11 +00004871{
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004872 CDataObject *self = (CDataObject *)_self;
Thomas Hellere81c9f62007-06-08 18:20:09 +00004873 Py_ssize_t size;
Thomas Heller45f59ab2006-06-10 19:51:46 +00004874 Py_ssize_t offset;
4875 StgDictObject *stgdict, *itemdict;
4876 PyObject *proto;
Thomas Hellerd4c93202006-03-08 19:35:11 +00004877
4878 if (value == NULL) {
4879 PyErr_SetString(PyExc_TypeError,
4880 "Pointer does not support item deletion");
4881 return -1;
4882 }
4883
4884 if (*(void **)self->b_ptr == NULL) {
4885 PyErr_SetString(PyExc_ValueError,
4886 "NULL pointer access");
4887 return -1;
4888 }
4889
4890 stgdict = PyObject_stgdict((PyObject *)self);
Thomas Hellerd32e6162006-08-16 13:03:11 +00004891 assert(stgdict); /* Cannot be NULL fr pointer instances */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004892
Thomas Heller45f59ab2006-06-10 19:51:46 +00004893 proto = stgdict->proto;
Thomas Hellerd32e6162006-08-16 13:03:11 +00004894 assert(proto);
4895
Thomas Heller45f59ab2006-06-10 19:51:46 +00004896 itemdict = PyType_stgdict(proto);
Thomas Heller0b21b432006-08-18 14:38:46 +00004897 assert(itemdict); /* Cannot be NULL because the itemtype of a pointer
4898 is always a ctypes type */
4899
Thomas Heller45f59ab2006-06-10 19:51:46 +00004900 size = itemdict->size;
4901 offset = index * itemdict->size;
4902
Thomas Heller5c6af802009-04-24 20:31:47 +00004903 return PyCData_set((PyObject *)self, proto, stgdict->setfunc, value,
Thomas Heller45f59ab2006-06-10 19:51:46 +00004904 index, size, (*(char **)self->b_ptr) + offset);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004905}
4906
4907static PyObject *
4908Pointer_get_contents(CDataObject *self, void *closure)
4909{
4910 StgDictObject *stgdict;
4911
4912 if (*(void **)self->b_ptr == NULL) {
4913 PyErr_SetString(PyExc_ValueError,
4914 "NULL pointer access");
4915 return NULL;
4916 }
4917
4918 stgdict = PyObject_stgdict((PyObject *)self);
Thomas Hellerd32e6162006-08-16 13:03:11 +00004919 assert(stgdict); /* Cannot be NULL fr pointer instances */
Thomas Heller5c6af802009-04-24 20:31:47 +00004920 return PyCData_FromBaseObj(stgdict->proto,
Thomas Heller45f59ab2006-06-10 19:51:46 +00004921 (PyObject *)self, 0,
4922 *(void **)self->b_ptr);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004923}
4924
4925static int
4926Pointer_set_contents(CDataObject *self, PyObject *value, void *closure)
4927{
4928 StgDictObject *stgdict;
4929 CDataObject *dst;
4930 PyObject *keep;
4931
4932 if (value == NULL) {
4933 PyErr_SetString(PyExc_TypeError,
4934 "Pointer does not support item deletion");
4935 return -1;
4936 }
4937 stgdict = PyObject_stgdict((PyObject *)self);
Thomas Hellerd32e6162006-08-16 13:03:11 +00004938 assert(stgdict); /* Cannot be NULL fr pointer instances */
Thomas Hellerd4c93202006-03-08 19:35:11 +00004939 assert(stgdict->proto);
4940 if (!CDataObject_Check(value)
4941 || 0 == PyObject_IsInstance(value, stgdict->proto)) {
4942 /* XXX PyObject_IsInstance could return -1! */
4943 PyErr_Format(PyExc_TypeError,
4944 "expected %s instead of %s",
4945 ((PyTypeObject *)(stgdict->proto))->tp_name,
Christian Heimese93237d2007-12-19 02:37:44 +00004946 Py_TYPE(value)->tp_name);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004947 return -1;
4948 }
4949
4950 dst = (CDataObject *)value;
4951 *(void **)self->b_ptr = dst->b_ptr;
4952
4953 /*
4954 A Pointer instance must keep a the value it points to alive. So, a
4955 pointer instance has b_length set to 2 instead of 1, and we set
4956 'value' itself as the second item of the b_objects list, additionally.
4957 */
4958 Py_INCREF(value);
4959 if (-1 == KeepRef(self, 1, value))
4960 return -1;
4961
4962 keep = GetKeepedObjects(dst);
4963 Py_INCREF(keep);
4964 return KeepRef(self, 0, keep);
4965}
4966
Thomas Hellerd4c93202006-03-08 19:35:11 +00004967static PyGetSetDef Pointer_getsets[] = {
4968 { "contents", (getter)Pointer_get_contents,
4969 (setter)Pointer_set_contents,
4970 "the object this pointer points to (read-write)", NULL },
Thomas Hellerd4c93202006-03-08 19:35:11 +00004971 { NULL, NULL }
4972};
4973
4974static int
4975Pointer_init(CDataObject *self, PyObject *args, PyObject *kw)
4976{
4977 PyObject *value = NULL;
4978
Thomas Hellerd3ed4922008-04-11 14:20:26 +00004979 if (!PyArg_UnpackTuple(args, "POINTER", 0, 1, &value))
Thomas Hellerd4c93202006-03-08 19:35:11 +00004980 return -1;
4981 if (value == NULL)
4982 return 0;
4983 return Pointer_set_contents(self, value, NULL);
4984}
4985
4986static PyObject *
4987Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4988{
4989 StgDictObject *dict = PyType_stgdict((PyObject *)type);
4990 if (!dict || !dict->proto) {
4991 PyErr_SetString(PyExc_TypeError,
4992 "Cannot create instance: has no _type_");
4993 return NULL;
4994 }
Thomas Heller5c6af802009-04-24 20:31:47 +00004995 return GenericPyCData_new(type, args, kw);
Thomas Hellerd4c93202006-03-08 19:35:11 +00004996}
4997
4998static PyObject *
Thomas Hellerba29e4c2006-03-20 10:22:42 +00004999Pointer_slice(PyObject *_self, Py_ssize_t ilow, Py_ssize_t ihigh)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005000{
Thomas Hellerba29e4c2006-03-20 10:22:42 +00005001 CDataObject *self = (CDataObject *)_self;
Thomas Hellerd4c93202006-03-08 19:35:11 +00005002 PyListObject *np;
5003 StgDictObject *stgdict, *itemdict;
5004 PyObject *proto;
Thomas Hellerfe8f8622006-03-14 19:53:09 +00005005 Py_ssize_t i, len;
Thomas Hellerd4c93202006-03-08 19:35:11 +00005006
5007 if (ilow < 0)
5008 ilow = 0;
5009 if (ihigh < ilow)
5010 ihigh = ilow;
5011 len = ihigh - ilow;
5012
5013 stgdict = PyObject_stgdict((PyObject *)self);
Thomas Hellerd32e6162006-08-16 13:03:11 +00005014 assert(stgdict); /* Cannot be NULL fr pointer instances */
Thomas Hellerd4c93202006-03-08 19:35:11 +00005015 proto = stgdict->proto;
Thomas Hellerd32e6162006-08-16 13:03:11 +00005016 assert(proto);
Thomas Hellerd4c93202006-03-08 19:35:11 +00005017 itemdict = PyType_stgdict(proto);
Thomas Hellerd32e6162006-08-16 13:03:11 +00005018 assert(itemdict);
Thomas Heller5c6af802009-04-24 20:31:47 +00005019 if (itemdict->getfunc == _ctypes_get_fielddesc("c")->getfunc) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00005020 char *ptr = *(char **)self->b_ptr;
Gregory P. Smithdd96db62008-06-09 04:58:54 +00005021 return PyString_FromStringAndSize(ptr + ilow, len);
Thomas Hellerd4c93202006-03-08 19:35:11 +00005022#ifdef CTYPES_UNICODE
Thomas Heller5c6af802009-04-24 20:31:47 +00005023 } else if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) {
Thomas Hellerd4c93202006-03-08 19:35:11 +00005024 wchar_t *ptr = *(wchar_t **)self->b_ptr;
5025 return PyUnicode_FromWideChar(ptr + ilow, len);
5026#endif
5027 }
5028
5029 np = (PyListObject *) PyList_New(len);
5030 if (np == NULL)
5031 return NULL;
5032
5033 for (i = 0; i < len; i++) {
Thomas Hellerba29e4c2006-03-20 10:22:42 +00005034 PyObject *v = Pointer_item(_self, i+ilow);
Thomas Hellerd4c93202006-03-08 19:35:11 +00005035 PyList_SET_ITEM(np, i, v);
5036 }
5037 return (PyObject *)np;
5038}
5039
Thomas Woutersdcb3c382007-08-30 21:01:17 +00005040static PyObject *
5041Pointer_subscript(PyObject *_self, PyObject *item)
5042{
5043 CDataObject *self = (CDataObject *)_self;
5044 if (PyIndex_Check(item)) {
5045 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
5046 if (i == -1 && PyErr_Occurred())
5047 return NULL;
5048 return Pointer_item(_self, i);
5049 }
5050 else if (PySlice_Check(item)) {
5051 PySliceObject *slice = (PySliceObject *)item;
5052 Py_ssize_t start, stop, step;
5053 PyObject *np;
5054 StgDictObject *stgdict, *itemdict;
5055 PyObject *proto;
5056 Py_ssize_t i, len, cur;
5057
5058 /* Since pointers have no length, and we want to apply
5059 different semantics to negative indices than normal
5060 slicing, we have to dissect the slice object ourselves.*/
5061 if (slice->step == Py_None) {
5062 step = 1;
5063 }
5064 else {
5065 step = PyNumber_AsSsize_t(slice->step,
5066 PyExc_ValueError);
5067 if (step == -1 && PyErr_Occurred())
5068 return NULL;
5069 if (step == 0) {
5070 PyErr_SetString(PyExc_ValueError,
5071 "slice step cannot be zero");
5072 return NULL;
5073 }
5074 }
5075 if (slice->start == Py_None) {
5076 if (step < 0) {
5077 PyErr_SetString(PyExc_ValueError,
5078 "slice start is required "
5079 "for step < 0");
5080 return NULL;
5081 }
5082 start = 0;
5083 }
5084 else {
5085 start = PyNumber_AsSsize_t(slice->start,
5086 PyExc_ValueError);
5087 if (start == -1 && PyErr_Occurred())
5088 return NULL;
5089 }
5090 if (slice->stop == Py_None) {
5091 PyErr_SetString(PyExc_ValueError,
5092 "slice stop is required");
5093 return NULL;
5094 }
5095 stop = PyNumber_AsSsize_t(slice->stop,
5096 PyExc_ValueError);
5097 if (stop == -1 && PyErr_Occurred())
5098 return NULL;
5099 if ((step > 0 && start > stop) ||
5100 (step < 0 && start < stop))
5101 len = 0;
5102 else if (step > 0)
5103 len = (stop - start - 1) / step + 1;
5104 else
5105 len = (stop - start + 1) / step + 1;
5106
5107 stgdict = PyObject_stgdict((PyObject *)self);
5108 assert(stgdict); /* Cannot be NULL for pointer instances */
5109 proto = stgdict->proto;
5110 assert(proto);
5111 itemdict = PyType_stgdict(proto);
5112 assert(itemdict);
Thomas Heller5c6af802009-04-24 20:31:47 +00005113 if (itemdict->getfunc == _ctypes_get_fielddesc("c")->getfunc) {
Thomas Woutersdcb3c382007-08-30 21:01:17 +00005114 char *ptr = *(char **)self->b_ptr;
5115 char *dest;
5116
5117 if (len <= 0)
Gregory P. Smithdd96db62008-06-09 04:58:54 +00005118 return PyString_FromString("");
Thomas Woutersdcb3c382007-08-30 21:01:17 +00005119 if (step == 1) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +00005120 return PyString_FromStringAndSize(ptr + start,
Thomas Woutersdcb3c382007-08-30 21:01:17 +00005121 len);
5122 }
5123 dest = (char *)PyMem_Malloc(len);
5124 if (dest == NULL)
5125 return PyErr_NoMemory();
5126 for (cur = start, i = 0; i < len; cur += step, i++) {
5127 dest[i] = ptr[cur];
5128 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +00005129 np = PyString_FromStringAndSize(dest, len);
Thomas Woutersdcb3c382007-08-30 21:01:17 +00005130 PyMem_Free(dest);
5131 return np;
5132 }
5133#ifdef CTYPES_UNICODE
Thomas Heller5c6af802009-04-24 20:31:47 +00005134 if (itemdict->getfunc == _ctypes_get_fielddesc("u")->getfunc) {
Thomas Woutersdcb3c382007-08-30 21:01:17 +00005135 wchar_t *ptr = *(wchar_t **)self->b_ptr;
5136 wchar_t *dest;
5137
5138 if (len <= 0)
5139 return PyUnicode_FromUnicode(NULL, 0);
5140 if (step == 1) {
5141 return PyUnicode_FromWideChar(ptr + start,
5142 len);
5143 }
5144 dest = (wchar_t *)PyMem_Malloc(len * sizeof(wchar_t));
5145 if (dest == NULL)
5146 return PyErr_NoMemory();
5147 for (cur = start, i = 0; i < len; cur += step, i++) {
5148 dest[i] = ptr[cur];
5149 }
5150 np = PyUnicode_FromWideChar(dest, len);
5151 PyMem_Free(dest);
5152 return np;
5153 }
5154#endif
5155
5156 np = PyList_New(len);
5157 if (np == NULL)
5158 return NULL;
5159
5160 for (cur = start, i = 0; i < len; cur += step, i++) {
5161 PyObject *v = Pointer_item(_self, cur);
5162 PyList_SET_ITEM(np, i, v);
5163 }
5164 return np;
5165 }
5166 else {
5167 PyErr_SetString(PyExc_TypeError,
5168 "Pointer indices must be integer");
5169 return NULL;
5170 }
5171}
5172
Thomas Hellerd4c93202006-03-08 19:35:11 +00005173static PySequenceMethods Pointer_as_sequence = {
5174 0, /* inquiry sq_length; */
5175 0, /* binaryfunc sq_concat; */
5176 0, /* intargfunc sq_repeat; */
Thomas Hellerba29e4c2006-03-20 10:22:42 +00005177 Pointer_item, /* intargfunc sq_item; */
5178 Pointer_slice, /* intintargfunc sq_slice; */
5179 Pointer_ass_item, /* intobjargproc sq_ass_item; */
Thomas Hellerd4c93202006-03-08 19:35:11 +00005180 0, /* intintobjargproc sq_ass_slice; */
5181 0, /* objobjproc sq_contains; */
5182 /* Added in release 2.0 */
5183 0, /* binaryfunc sq_inplace_concat; */
5184 0, /* intargfunc sq_inplace_repeat; */
5185};
5186
Thomas Woutersdcb3c382007-08-30 21:01:17 +00005187static PyMappingMethods Pointer_as_mapping = {
5188 0,
5189 Pointer_subscript,
5190};
5191
Thomas Heller0ad5ae02008-08-19 19:25:04 +00005192static int
5193Pointer_nonzero(CDataObject *self)
5194{
5195 return (*(void **)self->b_ptr != NULL);
5196}
5197
5198static PyNumberMethods Pointer_as_number = {
5199 0, /* nb_add */
5200 0, /* nb_subtract */
5201 0, /* nb_multiply */
5202 0, /* nb_divide */
5203 0, /* nb_remainder */
5204 0, /* nb_divmod */
5205 0, /* nb_power */
5206 0, /* nb_negative */
5207 0, /* nb_positive */
5208 0, /* nb_absolute */
5209 (inquiry)Pointer_nonzero, /* nb_nonzero */
5210};
5211
Thomas Heller5c6af802009-04-24 20:31:47 +00005212PyTypeObject PyCPointer_Type = {
Martin v. Löwis68192102007-07-21 06:55:02 +00005213 PyVarObject_HEAD_INIT(NULL, 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005214 "_ctypes._Pointer",
5215 sizeof(CDataObject), /* tp_basicsize */
5216 0, /* tp_itemsize */
5217 0, /* tp_dealloc */
5218 0, /* tp_print */
5219 0, /* tp_getattr */
5220 0, /* tp_setattr */
5221 0, /* tp_compare */
5222 0, /* tp_repr */
5223 &Pointer_as_number, /* tp_as_number */
5224 &Pointer_as_sequence, /* tp_as_sequence */
Thomas Woutersdcb3c382007-08-30 21:01:17 +00005225 &Pointer_as_mapping, /* tp_as_mapping */
Thomas Hellerd4c93202006-03-08 19:35:11 +00005226 0, /* tp_hash */
5227 0, /* tp_call */
5228 0, /* tp_str */
5229 0, /* tp_getattro */
5230 0, /* tp_setattro */
Thomas Heller5c6af802009-04-24 20:31:47 +00005231 &PyCData_as_buffer, /* tp_as_buffer */
Thomas Heller2e75c452008-06-05 17:51:15 +00005232 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_NEWBUFFER | Py_TPFLAGS_BASETYPE, /* tp_flags */
Thomas Hellerd4c93202006-03-08 19:35:11 +00005233 "XXX to be provided", /* tp_doc */
Thomas Heller5c6af802009-04-24 20:31:47 +00005234 (traverseproc)PyCData_traverse, /* tp_traverse */
5235 (inquiry)PyCData_clear, /* tp_clear */
Thomas Hellerd4c93202006-03-08 19:35:11 +00005236 0, /* tp_richcompare */
5237 0, /* tp_weaklistoffset */
5238 0, /* tp_iter */
5239 0, /* tp_iternext */
5240 0, /* tp_methods */
5241 0, /* tp_members */
5242 Pointer_getsets, /* tp_getset */
5243 0, /* tp_base */
5244 0, /* tp_dict */
5245 0, /* tp_descr_get */
5246 0, /* tp_descr_set */
5247 0, /* tp_dictoffset */
5248 (initproc)Pointer_init, /* tp_init */
5249 0, /* tp_alloc */
5250 Pointer_new, /* tp_new */
5251 0, /* tp_free */
5252};
5253
5254
5255/******************************************************************/
5256/*
5257 * Module initialization.
5258 */
5259
5260static char *module_docs =
5261"Create and manipulate C compatible data types in Python.";
5262
5263#ifdef MS_WIN32
5264
5265static char comerror_doc[] = "Raised when a COM method call failed.";
5266
5267static PyObject *
Thomas Hellerd4c93202006-03-08 19:35:11 +00005268comerror_init(PyObject *self, PyObject *args)
5269{
5270 PyObject *hresult, *text, *details;
5271 PyObject *a;
5272 int status;
5273
5274 if (!PyArg_ParseTuple(args, "OOOO:COMError", &self, &hresult, &text, &details))
5275 return NULL;
5276
5277 a = PySequence_GetSlice(args, 1, PySequence_Size(args));
5278 if (!a)
5279 return NULL;
5280 status = PyObject_SetAttrString(self, "args", a);
5281 Py_DECREF(a);
5282 if (status < 0)
5283 return NULL;
5284
5285 if (PyObject_SetAttrString(self, "hresult", hresult) < 0)
5286 return NULL;
5287
5288 if (PyObject_SetAttrString(self, "text", text) < 0)
5289 return NULL;
5290
5291 if (PyObject_SetAttrString(self, "details", details) < 0)
5292 return NULL;
5293
5294 Py_INCREF(Py_None);
5295 return Py_None;
5296}
5297
5298static PyMethodDef comerror_methods[] = {
Thomas Hellerd4c93202006-03-08 19:35:11 +00005299 { "__init__", comerror_init, METH_VARARGS },
5300 { NULL, NULL },
5301};
5302
Thomas Hellerd4c93202006-03-08 19:35:11 +00005303static int
5304create_comerror(void)
5305{
5306 PyObject *dict = PyDict_New();
5307 PyMethodDef *methods = comerror_methods;
5308 PyObject *s;
5309 int status;
5310
Thomas Heller55b8c3e2008-02-06 20:29:17 +00005311 if (dict == NULL)
5312 return -1;
5313
Thomas Hellerd4c93202006-03-08 19:35:11 +00005314 while (methods->ml_name) {
5315 /* get a wrapper for the built-in function */
5316 PyObject *func = PyCFunction_New(methods, NULL);
5317 PyObject *meth;
5318 if (func == NULL)
Thomas Heller55b8c3e2008-02-06 20:29:17 +00005319 goto error;
Thomas Hellerd4c93202006-03-08 19:35:11 +00005320 meth = PyMethod_New(func, NULL, ComError);
5321 Py_DECREF(func);
5322 if (meth == NULL)
Thomas Heller55b8c3e2008-02-06 20:29:17 +00005323 goto error;
Thomas Hellerd4c93202006-03-08 19:35:11 +00005324 PyDict_SetItemString(dict, methods->ml_name, meth);
5325 Py_DECREF(meth);
5326 ++methods;
5327 }
Thomas Heller1421b002007-07-13 13:59:39 +00005328
Gregory P. Smithdd96db62008-06-09 04:58:54 +00005329 s = PyString_FromString(comerror_doc);
Thomas Hellerd4c93202006-03-08 19:35:11 +00005330 if (s == NULL)
Thomas Heller55b8c3e2008-02-06 20:29:17 +00005331 goto error;
Thomas Hellerd4c93202006-03-08 19:35:11 +00005332 status = PyDict_SetItemString(dict, "__doc__", s);
5333 Py_DECREF(s);
Thomas Heller55b8c3e2008-02-06 20:29:17 +00005334 if (status == -1)
5335 goto error;
Thomas Heller1421b002007-07-13 13:59:39 +00005336
5337 ComError = PyErr_NewException("_ctypes.COMError",
5338 NULL,
5339 dict);
5340 if (ComError == NULL)
Thomas Heller55b8c3e2008-02-06 20:29:17 +00005341 goto error;
Thomas Heller1421b002007-07-13 13:59:39 +00005342
5343 return 0;
Thomas Heller55b8c3e2008-02-06 20:29:17 +00005344 error:
5345 Py_DECREF(dict);
5346 return -1;
Thomas Hellerd4c93202006-03-08 19:35:11 +00005347}
5348
5349#endif
5350
5351static PyObject *
Thomas Hellerc2f77252007-03-09 19:21:28 +00005352string_at(const char *ptr, int size)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005353{
Thomas Hellerc2f77252007-03-09 19:21:28 +00005354 if (size == -1)
Gregory P. Smithdd96db62008-06-09 04:58:54 +00005355 return PyString_FromString(ptr);
5356 return PyString_FromStringAndSize(ptr, size);
Thomas Hellerd4c93202006-03-08 19:35:11 +00005357}
5358
Thomas Hellerb03cb602006-03-17 15:52:58 +00005359static int
5360cast_check_pointertype(PyObject *arg)
5361{
5362 StgDictObject *dict;
5363
Thomas Heller5c6af802009-04-24 20:31:47 +00005364 if (PyCPointerTypeObject_Check(arg))
Thomas Hellerb03cb602006-03-17 15:52:58 +00005365 return 1;
Thomas Heller5c6af802009-04-24 20:31:47 +00005366 if (PyCFuncPtrTypeObject_Check(arg))
Thomas Heller4b75a7c2006-04-21 16:48:56 +00005367 return 1;
Thomas Hellerb03cb602006-03-17 15:52:58 +00005368 dict = PyType_stgdict(arg);
5369 if (dict) {
Gregory P. Smithdd96db62008-06-09 04:58:54 +00005370 if (PyString_Check(dict->proto)
5371 && (strchr("sPzUZXO", PyString_AS_STRING(dict->proto)[0]))) {
Thomas Hellerb03cb602006-03-17 15:52:58 +00005372 /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */
5373 return 1;
5374 }
5375 }
5376 PyErr_Format(PyExc_TypeError,
5377 "cast() argument 2 must be a pointer type, not %s",
5378 PyType_Check(arg)
5379 ? ((PyTypeObject *)arg)->tp_name
Christian Heimese93237d2007-12-19 02:37:44 +00005380 : Py_TYPE(arg)->tp_name);
Thomas Hellerb03cb602006-03-17 15:52:58 +00005381 return 0;
5382}
5383
5384static PyObject *
Thomas Heller45f59ab2006-06-10 19:51:46 +00005385cast(void *ptr, PyObject *src, PyObject *ctype)
Thomas Hellerb03cb602006-03-17 15:52:58 +00005386{
5387 CDataObject *result;
5388 if (0 == cast_check_pointertype(ctype))
5389 return NULL;
5390 result = (CDataObject *)PyObject_CallFunctionObjArgs(ctype, NULL);
5391 if (result == NULL)
5392 return NULL;
Thomas Heller45f59ab2006-06-10 19:51:46 +00005393
5394 /*
5395 The casted objects '_objects' member:
5396
5397 It must certainly contain the source objects one.
5398 It must contain the source object itself.
5399 */
5400 if (CDataObject_Check(src)) {
5401 CDataObject *obj = (CDataObject *)src;
Thomas Heller5c6af802009-04-24 20:31:47 +00005402 /* PyCData_GetContainer will initialize src.b_objects, we need
Thomas Heller45f59ab2006-06-10 19:51:46 +00005403 this so it can be shared */
Thomas Heller5c6af802009-04-24 20:31:47 +00005404 PyCData_GetContainer(obj);
Thomas Heller45f59ab2006-06-10 19:51:46 +00005405 /* But we need a dictionary! */
5406 if (obj->b_objects == Py_None) {
5407 Py_DECREF(Py_None);
5408 obj->b_objects = PyDict_New();
Thomas Heller3de83e92006-08-01 16:54:43 +00005409 if (obj->b_objects == NULL)
5410 goto failed;
Thomas Heller45f59ab2006-06-10 19:51:46 +00005411 }
Thomas Heller2244af52006-09-07 19:09:54 +00005412 Py_XINCREF(obj->b_objects);
Thomas Heller45f59ab2006-06-10 19:51:46 +00005413 result->b_objects = obj->b_objects;
Thomas Hellerd3ed4922008-04-11 14:20:26 +00005414 if (result->b_objects && PyDict_CheckExact(result->b_objects)) {
Thomas Heller3de83e92006-08-01 16:54:43 +00005415 PyObject *index;
Thomas Heller45f59ab2006-06-10 19:51:46 +00005416 int rc;
Thomas Heller3de83e92006-08-01 16:54:43 +00005417 index = PyLong_FromVoidPtr((void *)src);
5418 if (index == NULL)
5419 goto failed;
Thomas Heller45f59ab2006-06-10 19:51:46 +00005420 rc = PyDict_SetItem(result->b_objects, index, src);
5421 Py_DECREF(index);
Thomas Heller3de83e92006-08-01 16:54:43 +00005422 if (rc == -1)
5423 goto failed;
Thomas Heller45f59ab2006-06-10 19:51:46 +00005424 }
5425 }
Thomas Hellerb03cb602006-03-17 15:52:58 +00005426 /* Should we assert that result is a pointer type? */
5427 memcpy(result->b_ptr, &ptr, sizeof(void *));
5428 return (PyObject *)result;
Thomas Heller3de83e92006-08-01 16:54:43 +00005429
5430 failed:
5431 Py_DECREF(result);
5432 return NULL;
Thomas Hellerb03cb602006-03-17 15:52:58 +00005433}
Thomas Hellerd4c93202006-03-08 19:35:11 +00005434
5435#ifdef CTYPES_UNICODE
5436static PyObject *
5437wstring_at(const wchar_t *ptr, int size)
5438{
Thomas Hellere81c9f62007-06-08 18:20:09 +00005439 Py_ssize_t ssize = size;
5440 if (ssize == -1)
5441 ssize = wcslen(ptr);
5442 return PyUnicode_FromWideChar(ptr, ssize);
Thomas Hellerd4c93202006-03-08 19:35:11 +00005443}
5444#endif
5445
Thomas Hellerfe8f8622006-03-14 19:53:09 +00005446PyMODINIT_FUNC
Thomas Hellerd4c93202006-03-08 19:35:11 +00005447init_ctypes(void)
5448{
5449 PyObject *m;
5450
5451/* Note:
5452 ob_type is the metatype (the 'type'), defaults to PyType_Type,
5453 tp_base is the base type, defaults to 'object' aka PyBaseObject_Type.
5454*/
Thomas Hellerb4dc2ef2006-07-13 09:53:47 +00005455#ifdef WITH_THREAD
Thomas Hellerd4c93202006-03-08 19:35:11 +00005456 PyEval_InitThreads();
Thomas Hellerbde08132006-06-29 18:34:15 +00005457#endif
Thomas Heller5c6af802009-04-24 20:31:47 +00005458 m = Py_InitModule3("_ctypes", _ctypes_module_methods, module_docs);
Thomas Hellerd4c93202006-03-08 19:35:11 +00005459 if (!m)
5460 return;
5461
Thomas Heller5c6af802009-04-24 20:31:47 +00005462 _ctypes_ptrtype_cache = PyDict_New();
5463 if (_ctypes_ptrtype_cache == NULL)
Thomas Heller046e6a42008-04-14 16:10:07 +00005464 return;
5465
Thomas Heller5c6af802009-04-24 20:31:47 +00005466 PyModule_AddObject(m, "_pointer_type_cache", (PyObject *)_ctypes_ptrtype_cache);
Thomas Heller046e6a42008-04-14 16:10:07 +00005467
Thomas Hellera06a1a82008-02-13 20:21:53 +00005468 _unpickle = PyObject_GetAttrString(m, "_unpickle");
5469 if (_unpickle == NULL)
5470 return;
5471
Thomas Hellerd4c93202006-03-08 19:35:11 +00005472 if (PyType_Ready(&PyCArg_Type) < 0)
5473 return;
5474
Thomas Heller5c6af802009-04-24 20:31:47 +00005475 if (PyType_Ready(&PyCThunk_Type) < 0)
Thomas Hellerbf027c42008-04-24 18:14:19 +00005476 return;
5477
Thomas Hellerd4c93202006-03-08 19:35:11 +00005478 /* StgDict is derived from PyDict_Type */
Thomas Heller5c6af802009-04-24 20:31:47 +00005479 PyCStgDict_Type.tp_base = &PyDict_Type;
5480 if (PyType_Ready(&PyCStgDict_Type) < 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005481 return;
5482
5483 /*************************************************
5484 *
5485 * Metaclasses
5486 */
5487
Thomas Heller5c6af802009-04-24 20:31:47 +00005488 PyCStructType_Type.tp_base = &PyType_Type;
5489 if (PyType_Ready(&PyCStructType_Type) < 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005490 return;
5491
5492 UnionType_Type.tp_base = &PyType_Type;
5493 if (PyType_Ready(&UnionType_Type) < 0)
5494 return;
5495
Thomas Heller5c6af802009-04-24 20:31:47 +00005496 PyCPointerType_Type.tp_base = &PyType_Type;
5497 if (PyType_Ready(&PyCPointerType_Type) < 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005498 return;
5499
Thomas Heller5c6af802009-04-24 20:31:47 +00005500 PyCArrayType_Type.tp_base = &PyType_Type;
5501 if (PyType_Ready(&PyCArrayType_Type) < 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005502 return;
5503
Thomas Heller5c6af802009-04-24 20:31:47 +00005504 PyCSimpleType_Type.tp_base = &PyType_Type;
5505 if (PyType_Ready(&PyCSimpleType_Type) < 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005506 return;
5507
Thomas Heller5c6af802009-04-24 20:31:47 +00005508 PyCFuncPtrType_Type.tp_base = &PyType_Type;
5509 if (PyType_Ready(&PyCFuncPtrType_Type) < 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005510 return;
5511
5512 /*************************************************
5513 *
5514 * Classes using a custom metaclass
5515 */
5516
Thomas Heller5c6af802009-04-24 20:31:47 +00005517 if (PyType_Ready(&PyCData_Type) < 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005518 return;
5519
Thomas Heller5c6af802009-04-24 20:31:47 +00005520 Py_TYPE(&Struct_Type) = &PyCStructType_Type;
5521 Struct_Type.tp_base = &PyCData_Type;
Thomas Hellerd4c93202006-03-08 19:35:11 +00005522 if (PyType_Ready(&Struct_Type) < 0)
5523 return;
5524 PyModule_AddObject(m, "Structure", (PyObject *)&Struct_Type);
5525
Christian Heimese93237d2007-12-19 02:37:44 +00005526 Py_TYPE(&Union_Type) = &UnionType_Type;
Thomas Heller5c6af802009-04-24 20:31:47 +00005527 Union_Type.tp_base = &PyCData_Type;
Thomas Hellerd4c93202006-03-08 19:35:11 +00005528 if (PyType_Ready(&Union_Type) < 0)
5529 return;
5530 PyModule_AddObject(m, "Union", (PyObject *)&Union_Type);
5531
Thomas Heller5c6af802009-04-24 20:31:47 +00005532 Py_TYPE(&PyCPointer_Type) = &PyCPointerType_Type;
5533 PyCPointer_Type.tp_base = &PyCData_Type;
5534 if (PyType_Ready(&PyCPointer_Type) < 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005535 return;
Thomas Heller5c6af802009-04-24 20:31:47 +00005536 PyModule_AddObject(m, "_Pointer", (PyObject *)&PyCPointer_Type);
Thomas Hellerd4c93202006-03-08 19:35:11 +00005537
Thomas Heller5c6af802009-04-24 20:31:47 +00005538 Py_TYPE(&PyCArray_Type) = &PyCArrayType_Type;
5539 PyCArray_Type.tp_base = &PyCData_Type;
5540 if (PyType_Ready(&PyCArray_Type) < 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005541 return;
Thomas Heller5c6af802009-04-24 20:31:47 +00005542 PyModule_AddObject(m, "Array", (PyObject *)&PyCArray_Type);
Thomas Hellerd4c93202006-03-08 19:35:11 +00005543
Thomas Heller5c6af802009-04-24 20:31:47 +00005544 Py_TYPE(&Simple_Type) = &PyCSimpleType_Type;
5545 Simple_Type.tp_base = &PyCData_Type;
Thomas Hellerd4c93202006-03-08 19:35:11 +00005546 if (PyType_Ready(&Simple_Type) < 0)
5547 return;
5548 PyModule_AddObject(m, "_SimpleCData", (PyObject *)&Simple_Type);
5549
Thomas Heller5c6af802009-04-24 20:31:47 +00005550 Py_TYPE(&PyCFuncPtr_Type) = &PyCFuncPtrType_Type;
5551 PyCFuncPtr_Type.tp_base = &PyCData_Type;
5552 if (PyType_Ready(&PyCFuncPtr_Type) < 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005553 return;
Thomas Heller5c6af802009-04-24 20:31:47 +00005554 PyModule_AddObject(m, "CFuncPtr", (PyObject *)&PyCFuncPtr_Type);
Thomas Hellerd4c93202006-03-08 19:35:11 +00005555
5556 /*************************************************
5557 *
5558 * Simple classes
5559 */
5560
Thomas Heller5c6af802009-04-24 20:31:47 +00005561 /* PyCField_Type is derived from PyBaseObject_Type */
5562 if (PyType_Ready(&PyCField_Type) < 0)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005563 return;
5564
5565 /*************************************************
5566 *
5567 * Other stuff
5568 */
5569
Thomas Hellere4c03e42008-01-24 18:36:27 +00005570 DictRemover_Type.tp_new = PyType_GenericNew;
5571 if (PyType_Ready(&DictRemover_Type) < 0)
5572 return;
5573
Thomas Hellerd4c93202006-03-08 19:35:11 +00005574#ifdef MS_WIN32
5575 if (create_comerror() < 0)
5576 return;
5577 PyModule_AddObject(m, "COMError", ComError);
5578
5579 PyModule_AddObject(m, "FUNCFLAG_HRESULT", PyInt_FromLong(FUNCFLAG_HRESULT));
5580 PyModule_AddObject(m, "FUNCFLAG_STDCALL", PyInt_FromLong(FUNCFLAG_STDCALL));
5581#endif
5582 PyModule_AddObject(m, "FUNCFLAG_CDECL", PyInt_FromLong(FUNCFLAG_CDECL));
Thomas Hellerfbb9c0b2008-06-06 08:33:46 +00005583 PyModule_AddObject(m, "FUNCFLAG_USE_ERRNO", PyInt_FromLong(FUNCFLAG_USE_ERRNO));
5584 PyModule_AddObject(m, "FUNCFLAG_USE_LASTERROR", PyInt_FromLong(FUNCFLAG_USE_LASTERROR));
Thomas Hellerd4c93202006-03-08 19:35:11 +00005585 PyModule_AddObject(m, "FUNCFLAG_PYTHONAPI", PyInt_FromLong(FUNCFLAG_PYTHONAPI));
Thomas Heller9ae562e2007-01-10 20:51:19 +00005586 PyModule_AddStringConstant(m, "__version__", "1.1.0");
Thomas Hellerd4c93202006-03-08 19:35:11 +00005587
5588 PyModule_AddObject(m, "_memmove_addr", PyLong_FromVoidPtr(memmove));
5589 PyModule_AddObject(m, "_memset_addr", PyLong_FromVoidPtr(memset));
5590 PyModule_AddObject(m, "_string_at_addr", PyLong_FromVoidPtr(string_at));
Thomas Hellerb03cb602006-03-17 15:52:58 +00005591 PyModule_AddObject(m, "_cast_addr", PyLong_FromVoidPtr(cast));
Thomas Hellerd4c93202006-03-08 19:35:11 +00005592#ifdef CTYPES_UNICODE
5593 PyModule_AddObject(m, "_wstring_at_addr", PyLong_FromVoidPtr(wstring_at));
5594#endif
5595
Thomas Hellerfff61ea2006-04-06 15:23:16 +00005596/* If RTLD_LOCAL is not defined (Windows!), set it to zero. */
5597#ifndef RTLD_LOCAL
5598#define RTLD_LOCAL 0
5599#endif
5600
5601/* If RTLD_GLOBAL is not defined (cygwin), set it to the same value as
5602 RTLD_LOCAL.
5603*/
5604#ifndef RTLD_GLOBAL
5605#define RTLD_GLOBAL RTLD_LOCAL
5606#endif
5607
Thomas Hellerd4c93202006-03-08 19:35:11 +00005608 PyModule_AddObject(m, "RTLD_LOCAL", PyInt_FromLong(RTLD_LOCAL));
5609 PyModule_AddObject(m, "RTLD_GLOBAL", PyInt_FromLong(RTLD_GLOBAL));
Thomas Hellerd4c93202006-03-08 19:35:11 +00005610
5611 PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL);
5612 if (PyExc_ArgError) {
5613 Py_INCREF(PyExc_ArgError);
5614 PyModule_AddObject(m, "ArgumentError", PyExc_ArgError);
5615 }
Thomas Hellerd4c93202006-03-08 19:35:11 +00005616}
5617
5618/*****************************************************************
Thomas Heller9f902472006-07-14 15:01:05 +00005619 * replacements for broken Python api functions (in Python 2.3).
5620 * See #1047269 Buffer overwrite in PyUnicode_AsWideChar
Thomas Hellerd4c93202006-03-08 19:35:11 +00005621 */
5622
Thomas Heller5c6af802009-04-24 20:31:47 +00005623#if (PY_VERSION_HEX < 0x02040000)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005624#ifdef HAVE_WCHAR_H
5625
5626PyObject *My_PyUnicode_FromWideChar(register const wchar_t *w,
Thomas Heller9f902472006-07-14 15:01:05 +00005627 Py_ssize_t size)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005628{
5629 PyUnicodeObject *unicode;
5630
5631 if (w == NULL) {
5632 PyErr_BadInternalCall();
5633 return NULL;
5634 }
5635
5636 unicode = (PyUnicodeObject *)PyUnicode_FromUnicode(NULL, size);
5637 if (!unicode)
5638 return NULL;
5639
5640 /* Copy the wchar_t data into the new object */
5641#ifdef HAVE_USABLE_WCHAR_T
5642 memcpy(unicode->str, w, size * sizeof(wchar_t));
5643#else
5644 {
5645 register Py_UNICODE *u;
5646 register int i;
5647 u = PyUnicode_AS_UNICODE(unicode);
5648 /* In Python, the following line has a one-off error */
5649 for (i = size; i > 0; i--)
5650 *u++ = *w++;
5651 }
5652#endif
5653
5654 return (PyObject *)unicode;
5655}
5656
Thomas Hellere81c9f62007-06-08 18:20:09 +00005657Py_ssize_t My_PyUnicode_AsWideChar(PyUnicodeObject *unicode,
Thomas Hellerd4c93202006-03-08 19:35:11 +00005658 register wchar_t *w,
Thomas Heller9f902472006-07-14 15:01:05 +00005659 Py_ssize_t size)
Thomas Hellerd4c93202006-03-08 19:35:11 +00005660{
5661 if (unicode == NULL) {
5662 PyErr_BadInternalCall();
5663 return -1;
5664 }
5665 if (size > PyUnicode_GET_SIZE(unicode))
5666 size = PyUnicode_GET_SIZE(unicode);
5667#ifdef HAVE_USABLE_WCHAR_T
5668 memcpy(w, unicode->str, size * sizeof(wchar_t));
5669#else
5670 {
5671 register Py_UNICODE *u;
5672 register int i;
5673 u = PyUnicode_AS_UNICODE(unicode);
5674 /* In Python, the following line has a one-off error */
5675 for (i = size; i > 0; i--)
5676 *w++ = *u++;
5677 }
5678#endif
5679
5680 return size;
5681}
Thomas Heller5c6af802009-04-24 20:31:47 +00005682#endif
Thomas Hellerd4c93202006-03-08 19:35:11 +00005683#endif
5684
5685/*
5686 Local Variables:
5687 compile-command: "cd .. && python setup.py -q build -g && python setup.py -q build install --home ~"
5688 End:
5689*/