1 /*****************************************************************
2 This file should be kept compatible with Python 2.3, see PEP 291.
3 *****************************************************************/
13 /******************************************************************/
18 PyCField_new(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwds
)
21 obj
= (CFieldObject
*)type
->tp_alloc(type
, 0);
22 return (PyObject
*)obj
;
26 * Expects the size, index and offset for the current field in *psize and
27 * *poffset, stores the total size so far in *psize, the offset for the next
28 * field in *poffset, the alignment requirements for the current field in
29 * *palign, and returns a field desriptor for this field.
32 * bitfields extension:
33 * bitsize != 0: this is a bit field.
34 * pbitofs points to the current bit offset, this will be updated.
35 * prev_desc points to the type of the previous bitfield, if any.
38 PyCField_FromDesc(PyObject
*desc
, Py_ssize_t index
,
39 Py_ssize_t
*pfield_size
, int bitsize
, int *pbitofs
,
40 Py_ssize_t
*psize
, Py_ssize_t
*poffset
, Py_ssize_t
*palign
,
41 int pack
, int big_endian
)
45 Py_ssize_t size
, align
, length
;
46 SETFUNC setfunc
= NULL
;
47 GETFUNC getfunc
= NULL
;
51 #define NEW_BITFIELD 1
52 #define CONT_BITFIELD 2
53 #define EXPAND_BITFIELD 3
55 self
= (CFieldObject
*)PyObject_CallObject((PyObject
*)&PyCField_Type
,
59 dict
= PyType_stgdict(desc
);
61 PyErr_SetString(PyExc_TypeError
,
66 if (bitsize
/* this is a bitfield request */
67 && *pfield_size
/* we have a bitfield open */
69 /* MSVC, GCC with -mms-bitfields */
70 && dict
->size
* 8 == *pfield_size
73 && dict
->size
* 8 <= *pfield_size
75 && (*pbitofs
+ bitsize
) <= *pfield_size
) {
76 /* continue bit field */
77 fieldtype
= CONT_BITFIELD
;
79 } else if (bitsize
/* this is a bitfield request */
80 && *pfield_size
/* we have a bitfield open */
81 && dict
->size
* 8 >= *pfield_size
82 && (*pbitofs
+ bitsize
) <= dict
->size
* 8) {
83 /* expand bit field */
84 fieldtype
= EXPAND_BITFIELD
;
87 /* start new bitfield */
88 fieldtype
= NEW_BITFIELD
;
90 *pfield_size
= dict
->size
* 8;
93 fieldtype
= NO_BITFIELD
;
99 length
= dict
->length
;
102 /* Field descriptors for 'c_char * n' are be scpecial cased to
103 return a Python string instead of an Array object instance...
105 if (PyCArrayTypeObject_Check(proto
)) {
106 StgDictObject
*adict
= PyType_stgdict(proto
);
107 StgDictObject
*idict
;
108 if (adict
&& adict
->proto
) {
109 idict
= PyType_stgdict(adict
->proto
);
111 PyErr_SetString(PyExc_TypeError
,
116 if (idict
->getfunc
== _ctypes_get_fielddesc("c")->getfunc
) {
117 struct fielddesc
*fd
= _ctypes_get_fielddesc("s");
118 getfunc
= fd
->getfunc
;
119 setfunc
= fd
->setfunc
;
121 #ifdef CTYPES_UNICODE
122 if (idict
->getfunc
== _ctypes_get_fielddesc("u")->getfunc
) {
123 struct fielddesc
*fd
= _ctypes_get_fielddesc("U");
124 getfunc
= fd
->getfunc
;
125 setfunc
= fd
->setfunc
;
131 self
->setfunc
= setfunc
;
132 self
->getfunc
= getfunc
;
141 self
->size
= (bitsize
<< 16) + *pfield_size
- *pbitofs
- bitsize
;
143 self
->size
= (bitsize
<< 16) + *pbitofs
;
148 align
= min(pack
, dict
->align
);
151 if (align
&& *poffset
% align
) {
152 Py_ssize_t delta
= align
- (*poffset
% align
);
161 self
->offset
= *poffset
;
167 case EXPAND_BITFIELD
:
168 *poffset
+= dict
->size
- *pfield_size
/8;
169 *psize
+= dict
->size
- *pfield_size
/8;
171 *pfield_size
= dict
->size
* 8;
174 self
->size
= (bitsize
<< 16) + *pfield_size
- *pbitofs
- bitsize
;
176 self
->size
= (bitsize
<< 16) + *pbitofs
;
178 self
->offset
= *poffset
- size
; /* poffset is already updated for the NEXT field */
184 self
->size
= (bitsize
<< 16) + *pfield_size
- *pbitofs
- bitsize
;
186 self
->size
= (bitsize
<< 16) + *pbitofs
;
188 self
->offset
= *poffset
- size
; /* poffset is already updated for the NEXT field */
193 return (PyObject
*)self
;
197 PyCField_set(CFieldObject
*self
, PyObject
*inst
, PyObject
*value
)
201 assert(CDataObject_Check(inst
));
202 dst
= (CDataObject
*)inst
;
203 ptr
= dst
->b_ptr
+ self
->offset
;
205 PyErr_SetString(PyExc_TypeError
,
206 "can't delete attribute");
209 return PyCData_set(inst
, self
->proto
, self
->setfunc
, value
,
210 self
->index
, self
->size
, ptr
);
214 PyCField_get(CFieldObject
*self
, PyObject
*inst
, PyTypeObject
*type
)
219 return (PyObject
*)self
;
221 assert(CDataObject_Check(inst
));
222 src
= (CDataObject
*)inst
;
223 return PyCData_get(self
->proto
, self
->getfunc
, inst
,
224 self
->index
, self
->size
, src
->b_ptr
+ self
->offset
);
228 PyCField_get_offset(PyObject
*self
, void *data
)
230 return PyInt_FromSsize_t(((CFieldObject
*)self
)->offset
);
234 PyCField_get_size(PyObject
*self
, void *data
)
236 return PyInt_FromSsize_t(((CFieldObject
*)self
)->size
);
239 static PyGetSetDef PyCField_getset
[] = {
240 { "offset", PyCField_get_offset
, NULL
, "offset in bytes of this field" },
241 { "size", PyCField_get_size
, NULL
, "size in bytes of this field" },
242 { NULL
, NULL
, NULL
, NULL
},
246 PyCField_traverse(CFieldObject
*self
, visitproc visit
, void *arg
)
248 Py_VISIT(self
->proto
);
253 PyCField_clear(CFieldObject
*self
)
255 Py_CLEAR(self
->proto
);
260 PyCField_dealloc(PyObject
*self
)
262 PyCField_clear((CFieldObject
*)self
);
263 self
->ob_type
->tp_free((PyObject
*)self
);
267 PyCField_repr(CFieldObject
*self
)
270 Py_ssize_t bits
= self
->size
>> 16;
271 Py_ssize_t size
= self
->size
& 0xFFFF;
274 name
= ((PyTypeObject
*)self
->proto
)->tp_name
;
277 result
= PyString_FromFormat(
278 #if (PY_VERSION_HEX < 0x02050000)
279 "<Field type=%s, ofs=%d:%d, bits=%d>",
281 "<Field type=%s, ofs=%zd:%zd, bits=%zd>",
283 name
, self
->offset
, size
, bits
);
285 result
= PyString_FromFormat(
286 #if (PY_VERSION_HEX < 0x02050000)
287 "<Field type=%s, ofs=%d, size=%d>",
289 "<Field type=%s, ofs=%zd, size=%zd>",
291 name
, self
->offset
, size
);
295 PyTypeObject PyCField_Type
= {
296 PyVarObject_HEAD_INIT(NULL
, 0)
297 "_ctypes.CField", /* tp_name */
298 sizeof(CFieldObject
), /* tp_basicsize */
300 PyCField_dealloc
, /* tp_dealloc */
305 (reprfunc
)PyCField_repr
, /* tp_repr */
306 0, /* tp_as_number */
307 0, /* tp_as_sequence */
308 0, /* tp_as_mapping */
314 0, /* tp_as_buffer */
315 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
, /* tp_flags */
316 "Structure/Union member", /* tp_doc */
317 (traverseproc
)PyCField_traverse
, /* tp_traverse */
318 (inquiry
)PyCField_clear
, /* tp_clear */
319 0, /* tp_richcompare */
320 0, /* tp_weaklistoffset */
325 PyCField_getset
, /* tp_getset */
328 (descrgetfunc
)PyCField_get
, /* tp_descr_get */
329 (descrsetfunc
)PyCField_set
, /* tp_descr_set */
330 0, /* tp_dictoffset */
333 PyCField_new
, /* tp_new */
338 /******************************************************************/
343 /* Derived from Modules/structmodule.c:
344 Helper routine to get a Python integer and raise the appropriate error
348 get_long(PyObject
*v
, long *p
)
351 if (PyFloat_Check(v
)) {
352 PyErr_SetString(PyExc_TypeError
,
353 "int expected instead of float");
356 x
= PyInt_AsUnsignedLongMask(v
);
357 if (x
== -1 && PyErr_Occurred())
363 /* Same, but handling unsigned long */
366 get_ulong(PyObject
*v
, unsigned long *p
)
369 if (PyFloat_Check(v
)) {
370 PyErr_SetString(PyExc_TypeError
,
371 "int expected instead of float");
374 x
= PyInt_AsUnsignedLongMask(v
);
375 if (x
== (unsigned long)-1 && PyErr_Occurred())
381 #ifdef HAVE_LONG_LONG
383 /* Same, but handling native long long. */
386 get_longlong(PyObject
*v
, PY_LONG_LONG
*p
)
389 if (PyFloat_Check(v
)) {
390 PyErr_SetString(PyExc_TypeError
,
391 "int expected instead of float");
394 x
= PyInt_AsUnsignedLongLongMask(v
);
395 if (x
== -1 && PyErr_Occurred())
401 /* Same, but handling native unsigned long long. */
404 get_ulonglong(PyObject
*v
, unsigned PY_LONG_LONG
*p
)
406 unsigned PY_LONG_LONG x
;
407 if (PyFloat_Check(v
)) {
408 PyErr_SetString(PyExc_TypeError
,
409 "int expected instead of float");
412 x
= PyInt_AsUnsignedLongLongMask(v
);
413 if (x
== (unsigned PY_LONG_LONG
)-1 && PyErr_Occurred())
421 /*****************************************************************
422 * Integer fields, with bitfield support
425 /* how to decode the size field, for integer get/set functions */
426 #define LOW_BIT(x) ((x) & 0xFFFF)
427 #define NUM_BITS(x) ((x) >> 16)
429 /* This seems nore a compiler issue than a Windows/non-Windows one */
431 # define BIT_MASK(size) ((1 << NUM_BITS(size))-1)
433 # define BIT_MASK(size) ((1LL << NUM_BITS(size))-1)
436 /* This macro CHANGES the first parameter IN PLACE. For proper sign handling,
437 we must first shift left, then right.
439 #define GET_BITFIELD(v, size) \
440 if (NUM_BITS(size)) { \
441 v <<= (sizeof(v)*8 - LOW_BIT(size) - NUM_BITS(size)); \
442 v >>= (sizeof(v)*8 - NUM_BITS(size)); \
445 /* This macro RETURNS the first parameter with the bit field CHANGED. */
446 #define SET(x, v, size) \
448 ( ( x & ~(BIT_MASK(size) << LOW_BIT(size)) ) | ( (v & BIT_MASK(size)) << LOW_BIT(size) ) ) \
451 /* byte swapping macros */
453 ( ( (v >> 8) & 0x00FF) | \
454 ( (v << 8) & 0xFF00) )
457 ( ( (v & 0x000000FF) << 24 ) | \
458 ( (v & 0x0000FF00) << 8 ) | \
459 ( (v & 0x00FF0000) >> 8 ) | \
460 ( ((v >> 24) & 0xFF)) )
464 ( ( (v & 0x00000000000000FFL) << 56 ) | \
465 ( (v & 0x000000000000FF00L) << 40 ) | \
466 ( (v & 0x0000000000FF0000L) << 24 ) | \
467 ( (v & 0x00000000FF000000L) << 8 ) | \
468 ( (v & 0x000000FF00000000L) >> 8 ) | \
469 ( (v & 0x0000FF0000000000L) >> 24 ) | \
470 ( (v & 0x00FF000000000000L) >> 40 ) | \
471 ( ((v >> 56) & 0xFF)) )
474 ( ( (v & 0x00000000000000FFLL) << 56 ) | \
475 ( (v & 0x000000000000FF00LL) << 40 ) | \
476 ( (v & 0x0000000000FF0000LL) << 24 ) | \
477 ( (v & 0x00000000FF000000LL) << 8 ) | \
478 ( (v & 0x000000FF00000000LL) >> 8 ) | \
479 ( (v & 0x0000FF0000000000LL) >> 24 ) | \
480 ( (v & 0x00FF000000000000LL) >> 40 ) | \
481 ( ((v >> 56) & 0xFF)) )
484 #define SWAP_INT SWAP_4
487 # define SWAP_LONG SWAP_4
488 #elif SIZEOF_LONG == 8
489 # define SWAP_LONG SWAP_8
491 /*****************************************************************
492 * The setter methods return an object which must be kept alive, to keep the
493 * data valid which has been stored in the memory block. The ctypes object
494 * instance inserts this object into its 'b_objects' list.
496 * For simple Python types like integers or characters, there is nothing that
497 * has to been kept alive, so Py_None is returned in these cases. But this
498 * makes inspecting the 'b_objects' list, which is accessible from Python for
499 * debugging, less useful.
501 * So, defining the _CTYPES_DEBUG_KEEP symbol returns the original value
502 * instead of Py_None.
505 #ifdef _CTYPES_DEBUG_KEEP
506 #define _RET(x) Py_INCREF(x); return x
508 #define _RET(X) Py_INCREF(Py_None); return Py_None
511 /*****************************************************************
512 * integer accessor methods, supporting bit fields
516 b_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
519 if (get_long(value
, &val
) < 0)
521 *(signed char *)ptr
= (signed char)SET(*(signed char *)ptr
, (signed char)val
, size
);
527 b_get(void *ptr
, Py_ssize_t size
)
529 signed char val
= *(signed char *)ptr
;
530 GET_BITFIELD(val
, size
);
531 return PyInt_FromLong(val
);
535 B_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
538 if (get_ulong(value
, &val
) < 0)
540 *(unsigned char *)ptr
= (unsigned char)SET(*(unsigned char*)ptr
,
541 (unsigned short)val
, size
);
547 B_get(void *ptr
, Py_ssize_t size
)
549 unsigned char val
= *(unsigned char *)ptr
;
550 GET_BITFIELD(val
, size
);
551 return PyInt_FromLong(val
);
555 h_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
559 if (get_long(value
, &val
) < 0)
561 memcpy(&x
, ptr
, sizeof(x
));
562 x
= SET(x
, (short)val
, size
);
563 memcpy(ptr
, &x
, sizeof(x
));
569 h_set_sw(void *ptr
, PyObject
*value
, Py_ssize_t size
)
573 if (get_long(value
, &val
) < 0)
575 memcpy(&field
, ptr
, sizeof(field
));
576 field
= SWAP_2(field
);
577 field
= SET(field
, (short)val
, size
);
578 field
= SWAP_2(field
);
579 memcpy(ptr
, &field
, sizeof(field
));
584 h_get(void *ptr
, Py_ssize_t size
)
587 memcpy(&val
, ptr
, sizeof(val
));
588 GET_BITFIELD(val
, size
);
589 return PyInt_FromLong((long)val
);
593 h_get_sw(void *ptr
, Py_ssize_t size
)
596 memcpy(&val
, ptr
, sizeof(val
));
598 GET_BITFIELD(val
, size
);
599 return PyInt_FromLong(val
);
603 H_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
607 if (get_ulong(value
, &val
) < 0)
609 memcpy(&x
, ptr
, sizeof(x
));
610 x
= SET(x
, (unsigned short)val
, size
);
611 memcpy(ptr
, &x
, sizeof(x
));
616 H_set_sw(void *ptr
, PyObject
*value
, Py_ssize_t size
)
619 unsigned short field
;
620 if (get_ulong(value
, &val
) < 0)
622 memcpy(&field
, ptr
, sizeof(field
));
623 field
= SWAP_2(field
);
624 field
= SET(field
, (unsigned short)val
, size
);
625 field
= SWAP_2(field
);
626 memcpy(ptr
, &field
, sizeof(field
));
632 H_get(void *ptr
, Py_ssize_t size
)
635 memcpy(&val
, ptr
, sizeof(val
));
636 GET_BITFIELD(val
, size
);
637 return PyInt_FromLong(val
);
641 H_get_sw(void *ptr
, Py_ssize_t size
)
644 memcpy(&val
, ptr
, sizeof(val
));
646 GET_BITFIELD(val
, size
);
647 return PyInt_FromLong(val
);
651 i_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
655 if (get_long(value
, &val
) < 0)
657 memcpy(&x
, ptr
, sizeof(x
));
658 x
= SET(x
, (int)val
, size
);
659 memcpy(ptr
, &x
, sizeof(x
));
664 i_set_sw(void *ptr
, PyObject
*value
, Py_ssize_t size
)
668 if (get_long(value
, &val
) < 0)
670 memcpy(&field
, ptr
, sizeof(field
));
671 field
= SWAP_INT(field
);
672 field
= SET(field
, (int)val
, size
);
673 field
= SWAP_INT(field
);
674 memcpy(ptr
, &field
, sizeof(field
));
680 i_get(void *ptr
, Py_ssize_t size
)
683 memcpy(&val
, ptr
, sizeof(val
));
684 GET_BITFIELD(val
, size
);
685 return PyInt_FromLong(val
);
689 i_get_sw(void *ptr
, Py_ssize_t size
)
692 memcpy(&val
, ptr
, sizeof(val
));
694 GET_BITFIELD(val
, size
);
695 return PyInt_FromLong(val
);
699 /* short BOOL - VARIANT_BOOL */
701 vBOOL_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
703 switch (PyObject_IsTrue(value
)) {
707 *(short int *)ptr
= VARIANT_FALSE
;
710 *(short int *)ptr
= VARIANT_TRUE
;
716 vBOOL_get(void *ptr
, Py_ssize_t size
)
718 return PyBool_FromLong((long)*(short int *)ptr
);
723 #define BOOL_TYPE _Bool
725 #define BOOL_TYPE char
727 #define SIZEOF__BOOL 1
731 bool_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
733 switch (PyObject_IsTrue(value
)) {
737 *(BOOL_TYPE
*)ptr
= 0;
740 *(BOOL_TYPE
*)ptr
= 1;
746 bool_get(void *ptr
, Py_ssize_t size
)
748 return PyBool_FromLong((long)*(BOOL_TYPE
*)ptr
);
752 I_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
756 if (get_ulong(value
, &val
) < 0)
758 memcpy(&x
, ptr
, sizeof(x
));
759 x
= SET(x
, (unsigned int)val
, size
);
760 memcpy(ptr
, &x
, sizeof(x
));
765 I_set_sw(void *ptr
, PyObject
*value
, Py_ssize_t size
)
769 if (get_ulong(value
, &val
) < 0)
771 memcpy(&field
, ptr
, sizeof(field
));
772 field
= (unsigned int)SET(field
, (unsigned int)val
, size
);
773 field
= SWAP_INT(field
);
774 memcpy(ptr
, &field
, sizeof(field
));
780 I_get(void *ptr
, Py_ssize_t size
)
783 memcpy(&val
, ptr
, sizeof(val
));
784 GET_BITFIELD(val
, size
);
785 return PyLong_FromUnsignedLong(val
);
789 I_get_sw(void *ptr
, Py_ssize_t size
)
792 memcpy(&val
, ptr
, sizeof(val
));
794 GET_BITFIELD(val
, size
);
795 return PyLong_FromUnsignedLong(val
);
799 l_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
803 if (get_long(value
, &val
) < 0)
805 memcpy(&x
, ptr
, sizeof(x
));
806 x
= SET(x
, val
, size
);
807 memcpy(ptr
, &x
, sizeof(x
));
812 l_set_sw(void *ptr
, PyObject
*value
, Py_ssize_t size
)
816 if (get_long(value
, &val
) < 0)
818 memcpy(&field
, ptr
, sizeof(field
));
819 field
= SWAP_LONG(field
);
820 field
= (long)SET(field
, val
, size
);
821 field
= SWAP_LONG(field
);
822 memcpy(ptr
, &field
, sizeof(field
));
828 l_get(void *ptr
, Py_ssize_t size
)
831 memcpy(&val
, ptr
, sizeof(val
));
832 GET_BITFIELD(val
, size
);
833 return PyInt_FromLong(val
);
837 l_get_sw(void *ptr
, Py_ssize_t size
)
840 memcpy(&val
, ptr
, sizeof(val
));
841 val
= SWAP_LONG(val
);
842 GET_BITFIELD(val
, size
);
843 return PyInt_FromLong(val
);
847 L_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
851 if (get_ulong(value
, &val
) < 0)
853 memcpy(&x
, ptr
, sizeof(x
));
854 x
= SET(x
, val
, size
);
855 memcpy(ptr
, &x
, sizeof(x
));
860 L_set_sw(void *ptr
, PyObject
*value
, Py_ssize_t size
)
864 if (get_ulong(value
, &val
) < 0)
866 memcpy(&field
, ptr
, sizeof(field
));
867 field
= SWAP_LONG(field
);
868 field
= (unsigned long)SET(field
, val
, size
);
869 field
= SWAP_LONG(field
);
870 memcpy(ptr
, &field
, sizeof(field
));
876 L_get(void *ptr
, Py_ssize_t size
)
879 memcpy(&val
, ptr
, sizeof(val
));
880 GET_BITFIELD(val
, size
);
881 return PyLong_FromUnsignedLong(val
);
885 L_get_sw(void *ptr
, Py_ssize_t size
)
888 memcpy(&val
, ptr
, sizeof(val
));
889 val
= SWAP_LONG(val
);
890 GET_BITFIELD(val
, size
);
891 return PyLong_FromUnsignedLong(val
);
894 #ifdef HAVE_LONG_LONG
896 q_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
900 if (get_longlong(value
, &val
) < 0)
902 memcpy(&x
, ptr
, sizeof(x
));
903 x
= SET(x
, val
, size
);
904 memcpy(ptr
, &x
, sizeof(x
));
909 q_set_sw(void *ptr
, PyObject
*value
, Py_ssize_t size
)
913 if (get_longlong(value
, &val
) < 0)
915 memcpy(&field
, ptr
, sizeof(field
));
916 field
= SWAP_8(field
);
917 field
= (PY_LONG_LONG
)SET(field
, val
, size
);
918 field
= SWAP_8(field
);
919 memcpy(ptr
, &field
, sizeof(field
));
924 q_get(void *ptr
, Py_ssize_t size
)
927 memcpy(&val
, ptr
, sizeof(val
));
928 GET_BITFIELD(val
, size
);
929 return PyLong_FromLongLong(val
);
933 q_get_sw(void *ptr
, Py_ssize_t size
)
936 memcpy(&val
, ptr
, sizeof(val
));
938 GET_BITFIELD(val
, size
);
939 return PyLong_FromLongLong(val
);
943 Q_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
945 unsigned PY_LONG_LONG val
;
946 unsigned PY_LONG_LONG x
;
947 if (get_ulonglong(value
, &val
) < 0)
949 memcpy(&x
, ptr
, sizeof(x
));
950 x
= SET(x
, val
, size
);
951 memcpy(ptr
, &x
, sizeof(x
));
956 Q_set_sw(void *ptr
, PyObject
*value
, Py_ssize_t size
)
958 unsigned PY_LONG_LONG val
;
959 unsigned PY_LONG_LONG field
;
960 if (get_ulonglong(value
, &val
) < 0)
962 memcpy(&field
, ptr
, sizeof(field
));
963 field
= SWAP_8(field
);
964 field
= (unsigned PY_LONG_LONG
)SET(field
, val
, size
);
965 field
= SWAP_8(field
);
966 memcpy(ptr
, &field
, sizeof(field
));
971 Q_get(void *ptr
, Py_ssize_t size
)
973 unsigned PY_LONG_LONG val
;
974 memcpy(&val
, ptr
, sizeof(val
));
975 GET_BITFIELD(val
, size
);
976 return PyLong_FromUnsignedLongLong(val
);
980 Q_get_sw(void *ptr
, Py_ssize_t size
)
982 unsigned PY_LONG_LONG val
;
983 memcpy(&val
, ptr
, sizeof(val
));
985 GET_BITFIELD(val
, size
);
986 return PyLong_FromUnsignedLongLong(val
);
990 /*****************************************************************
991 * non-integer accessor methods, not supporting bit fields
996 g_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
1000 x
= PyFloat_AsDouble(value
);
1001 if (x
== -1 && PyErr_Occurred()) {
1002 PyErr_Format(PyExc_TypeError
,
1003 " float expected instead of %s instance",
1004 value
->ob_type
->tp_name
);
1007 memcpy(ptr
, &x
, sizeof(long double));
1012 g_get(void *ptr
, Py_ssize_t size
)
1015 memcpy(&val
, ptr
, sizeof(long double));
1016 return PyFloat_FromDouble(val
);
1020 d_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
1024 x
= PyFloat_AsDouble(value
);
1025 if (x
== -1 && PyErr_Occurred()) {
1026 PyErr_Format(PyExc_TypeError
,
1027 " float expected instead of %s instance",
1028 value
->ob_type
->tp_name
);
1031 memcpy(ptr
, &x
, sizeof(double));
1036 d_get(void *ptr
, Py_ssize_t size
)
1039 memcpy(&val
, ptr
, sizeof(val
));
1040 return PyFloat_FromDouble(val
);
1044 d_set_sw(void *ptr
, PyObject
*value
, Py_ssize_t size
)
1048 x
= PyFloat_AsDouble(value
);
1049 if (x
== -1 && PyErr_Occurred()) {
1050 PyErr_Format(PyExc_TypeError
,
1051 " float expected instead of %s instance",
1052 value
->ob_type
->tp_name
);
1055 #ifdef WORDS_BIGENDIAN
1056 if (_PyFloat_Pack8(x
, (unsigned char *)ptr
, 1))
1059 if (_PyFloat_Pack8(x
, (unsigned char *)ptr
, 0))
1066 d_get_sw(void *ptr
, Py_ssize_t size
)
1068 #ifdef WORDS_BIGENDIAN
1069 return PyFloat_FromDouble(_PyFloat_Unpack8(ptr
, 1));
1071 return PyFloat_FromDouble(_PyFloat_Unpack8(ptr
, 0));
1076 f_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
1080 x
= (float)PyFloat_AsDouble(value
);
1081 if (x
== -1 && PyErr_Occurred()) {
1082 PyErr_Format(PyExc_TypeError
,
1083 " float expected instead of %s instance",
1084 value
->ob_type
->tp_name
);
1087 memcpy(ptr
, &x
, sizeof(x
));
1092 f_get(void *ptr
, Py_ssize_t size
)
1095 memcpy(&val
, ptr
, sizeof(val
));
1096 return PyFloat_FromDouble(val
);
1100 f_set_sw(void *ptr
, PyObject
*value
, Py_ssize_t size
)
1104 x
= (float)PyFloat_AsDouble(value
);
1105 if (x
== -1 && PyErr_Occurred()) {
1106 PyErr_Format(PyExc_TypeError
,
1107 " float expected instead of %s instance",
1108 value
->ob_type
->tp_name
);
1111 #ifdef WORDS_BIGENDIAN
1112 if (_PyFloat_Pack4(x
, (unsigned char *)ptr
, 1))
1115 if (_PyFloat_Pack4(x
, (unsigned char *)ptr
, 0))
1122 f_get_sw(void *ptr
, Py_ssize_t size
)
1124 #ifdef WORDS_BIGENDIAN
1125 return PyFloat_FromDouble(_PyFloat_Unpack4(ptr
, 1));
1127 return PyFloat_FromDouble(_PyFloat_Unpack4(ptr
, 0));
1132 py_object refcounts:
1134 1. If we have a py_object instance, O_get must Py_INCREF the returned
1135 object, of course. If O_get is called from a function result, no py_object
1136 instance is created - so callproc.c::GetResult has to call Py_DECREF.
1138 2. The memory block in py_object owns a refcount. So, py_object must call
1139 Py_DECREF on destruction. Maybe only when b_needsfree is non-zero.
1142 O_get(void *ptr
, Py_ssize_t size
)
1144 PyObject
*ob
= *(PyObject
**)ptr
;
1146 if (!PyErr_Occurred())
1147 /* Set an error if not yet set */
1148 PyErr_SetString(PyExc_ValueError
,
1149 "PyObject is NULL");
1157 O_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
1159 /* Hm, does the memory block need it's own refcount or not? */
1160 *(PyObject
**)ptr
= value
;
1167 c_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
1169 if (!PyString_Check(value
) || (1 != PyString_Size(value
))) {
1170 PyErr_Format(PyExc_TypeError
,
1171 "one character string expected");
1174 *(char *)ptr
= PyString_AS_STRING(value
)[0];
1180 c_get(void *ptr
, Py_ssize_t size
)
1182 return PyString_FromStringAndSize((char *)ptr
, 1);
1185 #ifdef CTYPES_UNICODE
1186 /* u - a single wchar_t character */
1188 u_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
1192 if (PyString_Check(value
)) {
1193 value
= PyUnicode_FromEncodedObject(value
,
1194 _ctypes_conversion_encoding
,
1195 _ctypes_conversion_errors
);
1198 } else if (!PyUnicode_Check(value
)) {
1199 PyErr_Format(PyExc_TypeError
,
1200 "unicode string expected instead of %s instance",
1201 value
->ob_type
->tp_name
);
1206 len
= PyUnicode_GET_SIZE(value
);
1209 PyErr_SetString(PyExc_TypeError
,
1210 "one character unicode string expected");
1214 *(wchar_t *)ptr
= PyUnicode_AS_UNICODE(value
)[0];
1222 u_get(void *ptr
, Py_ssize_t size
)
1224 return PyUnicode_FromWideChar((wchar_t *)ptr
, 1);
1227 /* U - a unicode string */
1229 U_get(void *ptr
, Py_ssize_t size
)
1235 size
/= sizeof(wchar_t); /* we count character units here, not bytes */
1237 result
= PyUnicode_FromWideChar((wchar_t *)ptr
, size
);
1240 /* We need 'result' to be able to count the characters with wcslen,
1241 since ptr may not be NUL terminated. If the length is smaller (if
1242 it was actually NUL terminated, we construct a new one and throw
1245 /* chop off at the first NUL character, if any. */
1246 p
= PyUnicode_AS_UNICODE(result
);
1247 for (len
= 0; len
< size
; ++len
)
1252 PyObject
*ob
= PyUnicode_FromWideChar((wchar_t *)ptr
, len
);
1260 U_set(void *ptr
, PyObject
*value
, Py_ssize_t length
)
1264 /* It's easier to calculate in characters than in bytes */
1265 length
/= sizeof(wchar_t);
1267 if (PyString_Check(value
)) {
1268 value
= PyUnicode_FromEncodedObject(value
,
1269 _ctypes_conversion_encoding
,
1270 _ctypes_conversion_errors
);
1273 } else if (!PyUnicode_Check(value
)) {
1274 PyErr_Format(PyExc_TypeError
,
1275 "unicode string expected instead of %s instance",
1276 value
->ob_type
->tp_name
);
1280 size
= PyUnicode_GET_SIZE(value
);
1281 if (size
> length
) {
1282 PyErr_Format(PyExc_ValueError
,
1283 #if (PY_VERSION_HEX < 0x02050000)
1284 "string too long (%d, maximum length %d)",
1286 "string too long (%zd, maximum length %zd)",
1291 } else if (size
< length
-1)
1292 /* copy terminating NUL character if there is space */
1294 PyUnicode_AsWideChar((PyUnicodeObject
*)value
, (wchar_t *)ptr
, size
);
1301 s_get(void *ptr
, Py_ssize_t size
)
1306 result
= PyString_FromString((char *)ptr
);
1309 /* chop off at the first NUL character, if any.
1310 * On error, result will be deallocated and set to NULL.
1312 slen
= strlen(PyString_AS_STRING(result
));
1313 size
= min(size
, (Py_ssize_t
)slen
);
1314 if (result
->ob_refcnt
== 1) {
1315 /* shorten the result */
1316 _PyString_Resize(&result
, size
);
1319 /* cannot shorten the result */
1320 return PyString_FromStringAndSize(ptr
, size
);
1324 s_set(void *ptr
, PyObject
*value
, Py_ssize_t length
)
1329 data
= PyString_AsString(value
);
1332 size
= strlen(data
);
1333 if (size
< length
) {
1334 /* This will copy the leading NUL character
1335 * if there is space for it.
1338 } else if (size
> length
) {
1339 PyErr_Format(PyExc_ValueError
,
1340 #if (PY_VERSION_HEX < 0x02050000)
1341 "string too long (%d, maximum length %d)",
1343 "string too long (%zd, maximum length %zd)",
1348 /* Also copy the terminating NUL character if there is space */
1349 memcpy((char *)ptr
, data
, size
);
1354 z_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
1356 if (value
== Py_None
) {
1357 *(char **)ptr
= NULL
;
1361 if (PyString_Check(value
)) {
1362 *(char **)ptr
= PyString_AS_STRING(value
);
1365 } else if (PyUnicode_Check(value
)) {
1366 PyObject
*str
= PyUnicode_AsEncodedString(value
,
1367 _ctypes_conversion_encoding
,
1368 _ctypes_conversion_errors
);
1371 *(char **)ptr
= PyString_AS_STRING(str
);
1373 } else if (PyInt_Check(value
) || PyLong_Check(value
)) {
1374 #if SIZEOF_VOID_P == SIZEOF_LONG_LONG
1375 *(char **)ptr
= (char *)PyInt_AsUnsignedLongLongMask(value
);
1377 *(char **)ptr
= (char *)PyInt_AsUnsignedLongMask(value
);
1381 PyErr_Format(PyExc_TypeError
,
1382 "string or integer address expected instead of %s instance",
1383 value
->ob_type
->tp_name
);
1388 z_get(void *ptr
, Py_ssize_t size
)
1390 /* XXX What about invalid pointers ??? */
1391 if (*(void **)ptr
) {
1392 #if defined(MS_WIN32) && !defined(_WIN32_WCE)
1393 if (IsBadStringPtrA(*(char **)ptr
, -1)) {
1394 PyErr_Format(PyExc_ValueError
,
1395 "invalid string pointer %p",
1400 return PyString_FromString(*(char **)ptr
);
1407 #ifdef CTYPES_UNICODE
1409 Z_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
1411 if (value
== Py_None
) {
1412 *(wchar_t **)ptr
= NULL
;
1416 if (PyString_Check(value
)) {
1417 value
= PyUnicode_FromEncodedObject(value
,
1418 _ctypes_conversion_encoding
,
1419 _ctypes_conversion_errors
);
1422 } else if (PyInt_Check(value
) || PyLong_Check(value
)) {
1423 #if SIZEOF_VOID_P == SIZEOF_LONG_LONG
1424 *(wchar_t **)ptr
= (wchar_t *)PyInt_AsUnsignedLongLongMask(value
);
1426 *(wchar_t **)ptr
= (wchar_t *)PyInt_AsUnsignedLongMask(value
);
1430 } else if (!PyUnicode_Check(value
)) {
1431 PyErr_Format(PyExc_TypeError
,
1432 "unicode string or integer address expected instead of %s instance",
1433 value
->ob_type
->tp_name
);
1437 #ifdef HAVE_USABLE_WCHAR_T
1438 /* HAVE_USABLE_WCHAR_T means that Py_UNICODE and wchar_t is the same
1439 type. So we can copy directly. Hm, are unicode objects always NUL
1440 terminated in Python, internally?
1442 *(wchar_t **)ptr
= PyUnicode_AS_UNICODE(value
);
1446 /* We must create a wchar_t* buffer from the unicode object,
1447 and keep it alive */
1451 int size
= PyUnicode_GET_SIZE(value
);
1452 size
+= 1; /* terminating NUL */
1453 size
*= sizeof(wchar_t);
1454 buffer
= (wchar_t *)PyMem_Malloc(size
);
1457 return PyErr_NoMemory();
1459 memset(buffer
, 0, size
);
1460 keep
= PyCObject_FromVoidPtr(buffer
, PyMem_Free
);
1466 *(wchar_t **)ptr
= (wchar_t *)buffer
;
1467 if (-1 == PyUnicode_AsWideChar((PyUnicodeObject
*)value
,
1468 buffer
, PyUnicode_GET_SIZE(value
))) {
1480 Z_get(void *ptr
, Py_ssize_t size
)
1483 p
= *(wchar_t **)ptr
;
1485 #if defined(MS_WIN32) && !defined(_WIN32_WCE)
1486 if (IsBadStringPtrW(*(wchar_t **)ptr
, -1)) {
1487 PyErr_Format(PyExc_ValueError
,
1488 "invalid string pointer %p",
1493 return PyUnicode_FromWideChar(p
, wcslen(p
));
1503 BSTR_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
1507 /* convert value into a PyUnicodeObject or NULL */
1508 if (Py_None
== value
) {
1510 } else if (PyString_Check(value
)) {
1511 value
= PyUnicode_FromEncodedObject(value
,
1512 _ctypes_conversion_encoding
,
1513 _ctypes_conversion_errors
);
1516 } else if (PyUnicode_Check(value
)) {
1517 Py_INCREF(value
); /* for the descref below */
1519 PyErr_Format(PyExc_TypeError
,
1520 "unicode string expected instead of %s instance",
1521 value
->ob_type
->tp_name
);
1525 /* create a BSTR from value */
1527 Py_ssize_t size
= PyUnicode_GET_SIZE(value
);
1528 if ((unsigned) size
!= size
) {
1529 PyErr_SetString(PyExc_ValueError
, "String too long for BSTR");
1532 bstr
= SysAllocStringLen(PyUnicode_AS_UNICODE(value
),
1538 /* free the previous contents, if any */
1540 SysFreeString(*(BSTR
*)ptr
);
1543 *(BSTR
*)ptr
= bstr
;
1545 /* We don't need to keep any other object */
1551 BSTR_get(void *ptr
, Py_ssize_t size
)
1556 return PyUnicode_FromWideChar(p
, SysStringLen(p
));
1558 /* Hm, it seems NULL pointer and zero length string are the
1559 same in BSTR, see Don Box, p 81
1568 P_set(void *ptr
, PyObject
*value
, Py_ssize_t size
)
1571 if (value
== Py_None
) {
1572 *(void **)ptr
= NULL
;
1576 if (!PyInt_Check(value
) && !PyLong_Check(value
)) {
1577 PyErr_SetString(PyExc_TypeError
,
1578 "cannot be converted to pointer");
1582 #if SIZEOF_VOID_P <= SIZEOF_LONG
1583 v
= (void *)PyInt_AsUnsignedLongMask(value
);
1585 #ifndef HAVE_LONG_LONG
1586 # error "PyLong_AsVoidPtr: sizeof(void*) > sizeof(long), but no long long"
1587 #elif SIZEOF_LONG_LONG < SIZEOF_VOID_P
1588 # error "PyLong_AsVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)"
1590 v
= (void *)PyInt_AsUnsignedLongLongMask(value
);
1593 if (PyErr_Occurred())
1601 P_get(void *ptr
, Py_ssize_t size
)
1603 if (*(void **)ptr
== NULL
) {
1607 return PyLong_FromVoidPtr(*(void **)ptr
);
1610 static struct fielddesc formattable
[] = {
1611 { 's', s_set
, s_get
, &ffi_type_pointer
},
1612 { 'b', b_set
, b_get
, &ffi_type_schar
},
1613 { 'B', B_set
, B_get
, &ffi_type_uchar
},
1614 { 'c', c_set
, c_get
, &ffi_type_schar
},
1615 { 'd', d_set
, d_get
, &ffi_type_double
, d_set_sw
, d_get_sw
},
1616 { 'g', g_set
, g_get
, &ffi_type_longdouble
},
1617 { 'f', f_set
, f_get
, &ffi_type_float
, f_set_sw
, f_get_sw
},
1618 { 'h', h_set
, h_get
, &ffi_type_sshort
, h_set_sw
, h_get_sw
},
1619 { 'H', H_set
, H_get
, &ffi_type_ushort
, H_set_sw
, H_get_sw
},
1620 { 'i', i_set
, i_get
, &ffi_type_sint
, i_set_sw
, i_get_sw
},
1621 { 'I', I_set
, I_get
, &ffi_type_uint
, I_set_sw
, I_get_sw
},
1622 /* XXX Hm, sizeof(int) == sizeof(long) doesn't hold on every platform */
1623 /* As soon as we can get rid of the type codes, this is no longer a problem */
1624 #if SIZEOF_LONG == 4
1625 { 'l', l_set
, l_get
, &ffi_type_sint32
, l_set_sw
, l_get_sw
},
1626 { 'L', L_set
, L_get
, &ffi_type_uint32
, L_set_sw
, L_get_sw
},
1627 #elif SIZEOF_LONG == 8
1628 { 'l', l_set
, l_get
, &ffi_type_sint64
, l_set_sw
, l_get_sw
},
1629 { 'L', L_set
, L_get
, &ffi_type_uint64
, L_set_sw
, L_get_sw
},
1633 #ifdef HAVE_LONG_LONG
1634 #if SIZEOF_LONG_LONG == 8
1635 { 'q', q_set
, q_get
, &ffi_type_sint64
, q_set_sw
, q_get_sw
},
1636 { 'Q', Q_set
, Q_get
, &ffi_type_uint64
, Q_set_sw
, Q_get_sw
},
1641 { 'P', P_set
, P_get
, &ffi_type_pointer
},
1642 { 'z', z_set
, z_get
, &ffi_type_pointer
},
1643 #ifdef CTYPES_UNICODE
1644 { 'u', u_set
, u_get
, NULL
}, /* ffi_type set later */
1645 { 'U', U_set
, U_get
, &ffi_type_pointer
},
1646 { 'Z', Z_set
, Z_get
, &ffi_type_pointer
},
1649 { 'X', BSTR_set
, BSTR_get
, &ffi_type_pointer
},
1650 { 'v', vBOOL_set
, vBOOL_get
, &ffi_type_sshort
},
1652 #if SIZEOF__BOOL == 1
1653 { '?', bool_set
, bool_get
, &ffi_type_uchar
}, /* Also fallback for no native _Bool support */
1654 #elif SIZEOF__BOOL == SIZEOF_SHORT
1655 { '?', bool_set
, bool_get
, &ffi_type_ushort
},
1656 #elif SIZEOF__BOOL == SIZEOF_INT
1657 { '?', bool_set
, bool_get
, &ffi_type_uint
, I_set_sw
, I_get_sw
},
1658 #elif SIZEOF__BOOL == SIZEOF_LONG
1659 { '?', bool_set
, bool_get
, &ffi_type_ulong
, L_set_sw
, L_get_sw
},
1660 #elif SIZEOF__BOOL == SIZEOF_LONG_LONG
1661 { '?', bool_set
, bool_get
, &ffi_type_ulong
, Q_set_sw
, Q_get_sw
},
1662 #endif /* SIZEOF__BOOL */
1663 { 'O', O_set
, O_get
, &ffi_type_pointer
},
1664 { 0, NULL
, NULL
, NULL
},
1668 Ideas: Implement VARIANT in this table, using 'V' code.
1669 Use '?' as code for BOOL.
1673 _ctypes_get_fielddesc(char *fmt
)
1675 static int initialized
= 0;
1676 struct fielddesc
*table
= formattable
;
1680 #ifdef CTYPES_UNICODE
1681 if (sizeof(wchar_t) == sizeof(short))
1682 _ctypes_get_fielddesc("u")->pffi_type
= &ffi_type_sshort
;
1683 else if (sizeof(wchar_t) == sizeof(int))
1684 _ctypes_get_fielddesc("u")->pffi_type
= &ffi_type_sint
;
1685 else if (sizeof(wchar_t) == sizeof(long))
1686 _ctypes_get_fielddesc("u")->pffi_type
= &ffi_type_slong
;
1690 for (; table
->code
; ++table
) {
1691 if (table
->code
== fmt
[0])
1697 typedef struct { char c
; char x
; } s_char
;
1698 typedef struct { char c
; short x
; } s_short
;
1699 typedef struct { char c
; int x
; } s_int
;
1700 typedef struct { char c
; long x
; } s_long
;
1701 typedef struct { char c
; float x
; } s_float
;
1702 typedef struct { char c
; double x
; } s_double
;
1703 typedef struct { char c
; long double x
; } s_long_double
;
1704 typedef struct { char c
; char *x
; } s_char_p
;
1705 typedef struct { char c
; void *x
; } s_void_p
;
1708 #define CHAR_ALIGN (sizeof(s_char) - sizeof(char))
1709 #define SHORT_ALIGN (sizeof(s_short) - sizeof(short))
1710 #define INT_ALIGN (sizeof(s_int) - sizeof(int))
1711 #define LONG_ALIGN (sizeof(s_long) - sizeof(long))
1713 #define FLOAT_ALIGN (sizeof(s_float) - sizeof(float))
1714 #define DOUBLE_ALIGN (sizeof(s_double) - sizeof(double))
1715 #define LONGDOUBLE_ALIGN (sizeof(s_long_double) - sizeof(long double))
1717 /* #define CHAR_P_ALIGN (sizeof(s_char_p) - sizeof(char*)) */
1718 #define VOID_P_ALIGN (sizeof(s_void_p) - sizeof(void*))
1721 #ifdef HAVE_USABLE_WCHAR_T
1722 typedef struct { char c; wchar_t x; } s_wchar;
1723 typedef struct { char c; wchar_t *x; } s_wchar_p;
1725 #define WCHAR_ALIGN (sizeof(s_wchar) - sizeof(wchar_t))
1726 #define WCHAR_P_ALIGN (sizeof(s_wchar_p) - sizeof(wchar_t*))
1730 #ifdef HAVE_LONG_LONG
1731 typedef struct { char c
; PY_LONG_LONG x
; } s_long_long
;
1732 #define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(PY_LONG_LONG))
1736 typedef struct _ffi_type
1739 unsigned short alignment;
1740 unsigned short type;
1741 struct _ffi_type **elements;
1745 /* align and size are bogus for void, but they must not be zero */
1746 ffi_type ffi_type_void
= { 1, 1, FFI_TYPE_VOID
};
1748 ffi_type ffi_type_uint8
= { 1, 1, FFI_TYPE_UINT8
};
1749 ffi_type ffi_type_sint8
= { 1, 1, FFI_TYPE_SINT8
};
1751 ffi_type ffi_type_uint16
= { 2, 2, FFI_TYPE_UINT16
};
1752 ffi_type ffi_type_sint16
= { 2, 2, FFI_TYPE_SINT16
};
1754 ffi_type ffi_type_uint32
= { 4, 4, FFI_TYPE_UINT32
};
1755 ffi_type ffi_type_sint32
= { 4, 4, FFI_TYPE_SINT32
};
1757 ffi_type ffi_type_uint64
= { 8, LONG_LONG_ALIGN
, FFI_TYPE_UINT64
};
1758 ffi_type ffi_type_sint64
= { 8, LONG_LONG_ALIGN
, FFI_TYPE_SINT64
};
1760 ffi_type ffi_type_float
= { sizeof(float), FLOAT_ALIGN
, FFI_TYPE_FLOAT
};
1761 ffi_type ffi_type_double
= { sizeof(double), DOUBLE_ALIGN
, FFI_TYPE_DOUBLE
};
1763 #ifdef ffi_type_longdouble
1764 #undef ffi_type_longdouble
1766 /* This is already defined on OSX */
1767 ffi_type ffi_type_longdouble
= { sizeof(long double), LONGDOUBLE_ALIGN
,
1768 FFI_TYPE_LONGDOUBLE
};
1770 ffi_type ffi_type_pointer
= { sizeof(void *), VOID_P_ALIGN
, FFI_TYPE_POINTER
};
1772 /*---------------- EOF ----------------*/