cpython/Modules/_ctypes/cfield.c

#ifndef Py_BUILD_CORE_BUILTIN
#define Py_BUILD_CORE_MODULE
#endif

#include "Python.h"
// windows.h must be included before pycore internal headers
#ifdef MS_WIN32
#  include <windows.h>
#endif

#include "pycore_bitutils.h"      // _Py_bswap32()
#include "pycore_call.h"          // _PyObject_CallNoArgs()

#include <ffi.h>
#include "ctypes.h"

#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
#  include "../_complex.h"        // complex
#endif

#define CTYPES_CFIELD_CAPSULE_NAME_PYMEM

/*[clinic input]
module _ctypes
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=476a19c49b31a75c]*/

#include "clinic/cfield.c.h"

static void pymem_destructor(PyObject *ptr)
{}


/******************************************************************/
/*
  PyCField_Type
*/
/*[clinic input]
class _ctypes.CField "PyObject *" "PyObject"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=602817ea3ffc709c]*/

static inline
Py_ssize_t NUM_BITS(Py_ssize_t bitsize);
static inline
Py_ssize_t LOW_BIT(Py_ssize_t offset);


/*[clinic input]
@classmethod
_ctypes.CField.__new__ as PyCField_new

    name: object(subclass_of='&PyUnicode_Type')
    type as proto: object
    size: Py_ssize_t
    offset: Py_ssize_t
    index: Py_ssize_t
    bit_size as bit_size_obj: object = None

[clinic start generated code]*/

static PyObject *
PyCField_new_impl(PyTypeObject *type, PyObject *name, PyObject *proto,
                  Py_ssize_t size, Py_ssize_t offset, Py_ssize_t index,
                  PyObject *bit_size_obj)
/*[clinic end generated code: output=43649ef9157c5f58 input=3d813f56373c4caa]*/
{}


static int
PyCField_set(CFieldObject *self, PyObject *inst, PyObject *value)
{}

static PyObject *
PyCField_get(CFieldObject *self, PyObject *inst, PyTypeObject *type)
{}

static PyObject *
PyCField_get_offset(PyObject *self, void *data)
{}

static PyObject *
PyCField_get_size(PyObject *self, void *data)
{}

static PyGetSetDef PyCField_getset[] =;

static int
PyCField_traverse(CFieldObject *self, visitproc visit, void *arg)
{}

static int
PyCField_clear(CFieldObject *self)
{}

static void
PyCField_dealloc(PyObject *self)
{}

static PyObject *
PyCField_repr(CFieldObject *self)
{}

static PyType_Slot cfield_slots[] =;

PyType_Spec cfield_spec =;


/******************************************************************/
/*
  Accessor functions
*/

/* Derived from Modules/structmodule.c:
   Helper routine to get a Python integer and raise the appropriate error
   if it isn't one */

static int
get_long(PyObject *v, long *p)
{}

/* Same, but handling unsigned long */

static int
get_ulong(PyObject *v, unsigned long *p)
{}

/* Same, but handling native long long. */

static int
get_longlong(PyObject *v, long long *p)
{}

/* Same, but handling native unsigned long long. */

static int
get_ulonglong(PyObject *v, unsigned long long *p)
{}

/*****************************************************************
 * Integer fields, with bitfield support
 */

/* how to decode the size field, for integer get/set functions */
static inline
Py_ssize_t LOW_BIT(Py_ssize_t offset) {}
static inline
Py_ssize_t NUM_BITS(Py_ssize_t bitsize) {}

/* Doesn't work if NUM_BITS(size) == 0, but it never happens in SET() call. */
#define BIT_MASK(type, size)

/* This macro CHANGES the first parameter IN PLACE. For proper sign handling,
   we must first shift left, then right.
*/
#define GET_BITFIELD(v, size)

/* This macro RETURNS the first parameter with the bit field CHANGED. */
#define SET(type, x, v, size)

#if SIZEOF_SHORT == 2
#define SWAP_SHORT
#else
#  error "unsupported short size"
#endif

#if SIZEOF_INT == 4
#define SWAP_INT
#else
#  error "unsupported int size"
#endif

#if SIZEOF_LONG == 4
#define SWAP_LONG
#elif SIZEOF_LONG == 8
#define SWAP_LONG
#else
#  error "unsupported long size"
#endif

#if SIZEOF_LONG_LONG == 8
#define SWAP_LONG_LONG
#else
#  error "unsupported long long size"
#endif

/*****************************************************************
 * The setter methods return an object which must be kept alive, to keep the
 * data valid which has been stored in the memory block.  The ctypes object
 * instance inserts this object into its 'b_objects' list.
 *
 * For simple Python types like integers or characters, there is nothing that
 * has to been kept alive, so Py_None is returned in these cases.  But this
 * makes inspecting the 'b_objects' list, which is accessible from Python for
 * debugging, less useful.
 *
 * So, defining the _CTYPES_DEBUG_KEEP symbol returns the original value
 * instead of Py_None.
 */

#ifdef _CTYPES_DEBUG_KEEP
#define _RET
#else
#define _RET(X)
#endif

/*****************************************************************
 * integer accessor methods, supporting bit fields
 */

static PyObject *
b_set(void *ptr, PyObject *value, Py_ssize_t size)
{}


static PyObject *
b_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
B_set(void *ptr, PyObject *value, Py_ssize_t size)
{}


static PyObject *
B_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
h_set(void *ptr, PyObject *value, Py_ssize_t size)
{}


static PyObject *
h_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
h_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
h_get_sw(void *ptr, Py_ssize_t size)
{}

static PyObject *
H_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
H_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
{}


static PyObject *
H_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
H_get_sw(void *ptr, Py_ssize_t size)
{}

static PyObject *
i_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
i_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
{}


static PyObject *
i_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
i_get_sw(void *ptr, Py_ssize_t size)
{}

#ifndef MS_WIN32
/* http://msdn.microsoft.com/en-us/library/cc237864.aspx */
#define VARIANT_FALSE
#define VARIANT_TRUE
#endif
/* short BOOL - VARIANT_BOOL */
static PyObject *
vBOOL_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
vBOOL_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
bool_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
bool_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
I_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
I_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
{}


static PyObject *
I_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
I_get_sw(void *ptr, Py_ssize_t size)
{}

static PyObject *
l_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
l_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
{}


static PyObject *
l_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
l_get_sw(void *ptr, Py_ssize_t size)
{}

static PyObject *
L_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
L_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
{}


static PyObject *
L_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
L_get_sw(void *ptr, Py_ssize_t size)
{}

static PyObject *
q_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
q_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
q_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
q_get_sw(void *ptr, Py_ssize_t size)
{}

static PyObject *
Q_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
Q_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
Q_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
Q_get_sw(void *ptr, Py_ssize_t size)
{}

/*****************************************************************
 * non-integer accessor methods, not supporting bit fields
 */


static PyObject *
g_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
g_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
d_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
d_get(void *ptr, Py_ssize_t size)
{}

#if defined(Py_HAVE_C_COMPLEX) && defined(Py_FFI_SUPPORT_C_COMPLEX)
static PyObject *
C_set(void *ptr, PyObject *value, Py_ssize_t size)
{
    Py_complex c = PyComplex_AsCComplex(value);

    if (c.real == -1 && PyErr_Occurred()) {
        return NULL;
    }
    double complex x = CMPLX(c.real, c.imag);
    memcpy(ptr, &x, sizeof(x));
    _RET(value);
}

static PyObject *
C_get(void *ptr, Py_ssize_t size)
{
    double complex x;

    memcpy(&x, ptr, sizeof(x));
    return PyComplex_FromDoubles(creal(x), cimag(x));
}

static PyObject *
E_set(void *ptr, PyObject *value, Py_ssize_t size)
{
    Py_complex c = PyComplex_AsCComplex(value);

    if (c.real == -1 && PyErr_Occurred()) {
        return NULL;
    }
    float complex x = CMPLXF((float)c.real, (float)c.imag);
    memcpy(ptr, &x, sizeof(x));
    _RET(value);
}

static PyObject *
E_get(void *ptr, Py_ssize_t size)
{
    float complex x;

    memcpy(&x, ptr, sizeof(x));
    return PyComplex_FromDoubles(crealf(x), cimagf(x));
}

static PyObject *
F_set(void *ptr, PyObject *value, Py_ssize_t size)
{
    Py_complex c = PyComplex_AsCComplex(value);

    if (c.real == -1 && PyErr_Occurred()) {
        return NULL;
    }
    long double complex x = CMPLXL(c.real, c.imag);
    memcpy(ptr, &x, sizeof(x));
    _RET(value);
}

static PyObject *
F_get(void *ptr, Py_ssize_t size)
{
    long double complex x;

    memcpy(&x, ptr, sizeof(x));
    return PyComplex_FromDoubles((double)creall(x), (double)cimagl(x));
}
#endif

static PyObject *
d_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
d_get_sw(void *ptr, Py_ssize_t size)
{}

static PyObject *
f_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
f_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
f_set_sw(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
f_get_sw(void *ptr, Py_ssize_t size)
{}

/*
  py_object refcounts:

  1. If we have a py_object instance, O_get must Py_INCREF the returned
  object, of course.  If O_get is called from a function result, no py_object
  instance is created - so callproc.c::GetResult has to call Py_DECREF.

  2. The memory block in py_object owns a refcount.  So, py_object must call
  Py_DECREF on destruction.  Maybe only when b_needsfree is non-zero.
*/
static PyObject *
O_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
O_set(void *ptr, PyObject *value, Py_ssize_t size)
{}


static PyObject *
c_set(void *ptr, PyObject *value, Py_ssize_t size)
{}


static PyObject *
c_get(void *ptr, Py_ssize_t size)
{}

/* u - a single wchar_t character */
static PyObject *
u_set(void *ptr, PyObject *value, Py_ssize_t size)
{}


static PyObject *
u_get(void *ptr, Py_ssize_t size)
{}

/* U - a unicode string */
static PyObject *
U_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
U_set(void *ptr, PyObject *value, Py_ssize_t length)
{}


static PyObject *
s_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
s_set(void *ptr, PyObject *value, Py_ssize_t length)
{}

static PyObject *
z_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
z_get(void *ptr, Py_ssize_t size)
{}

static PyObject *
Z_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
Z_get(void *ptr, Py_ssize_t size)
{}


#ifdef MS_WIN32
static PyObject *
BSTR_set(void *ptr, PyObject *value, Py_ssize_t size)
{
    BSTR bstr;

    /* convert value into a PyUnicodeObject or NULL */
    if (Py_None == value) {
        value = NULL;
    } else if (!PyUnicode_Check(value)) {
        PyErr_Format(PyExc_TypeError,
                        "unicode string expected instead of %s instance",
                        Py_TYPE(value)->tp_name);
        return NULL;
    }

    /* create a BSTR from value */
    if (value) {
        Py_ssize_t wsize;
        wchar_t *wvalue = PyUnicode_AsWideCharString(value, &wsize);
        if (wvalue == NULL) {
            return NULL;
        }
        if ((unsigned) wsize != wsize) {
            PyErr_SetString(PyExc_ValueError, "String too long for BSTR");
            PyMem_Free(wvalue);
            return NULL;
        }
        bstr = SysAllocStringLen(wvalue, (unsigned)wsize);
        PyMem_Free(wvalue);
    } else
        bstr = NULL;

    /* free the previous contents, if any */
    if (*(BSTR *)ptr)
        SysFreeString(*(BSTR *)ptr);

    /* and store it */
    *(BSTR *)ptr = bstr;

    /* We don't need to keep any other object */
    _RET(value);
}


static PyObject *
BSTR_get(void *ptr, Py_ssize_t size)
{
    BSTR p;
    p = *(BSTR *)ptr;
    if (p)
        return PyUnicode_FromWideChar(p, SysStringLen(p));
    else {
        /* Hm, it seems NULL pointer and zero length string are the
           same in BSTR, see Don Box, p 81
        */
        Py_RETURN_NONE;
    }
}
#endif

static PyObject *
P_set(void *ptr, PyObject *value, Py_ssize_t size)
{}

static PyObject *
P_get(void *ptr, Py_ssize_t size)
{}

static struct fielddesc formattable[] =;

/*
  Ideas: Implement VARIANT in this table, using 'V' code.
  Use '?' as code for BOOL.
*/

/* Delayed initialization. Windows cannot statically reference dynamically
   loaded addresses from DLLs. */
void
_ctypes_init_fielddesc(void)
{}

struct fielddesc *
_ctypes_get_fielddesc(const char *fmt)
{}

/*---------------- EOF ----------------*/