Skip to content
Closed
Prev Previous commit
Next Next commit
ULong, private types, add module to call
  • Loading branch information
tiran committed Apr 17, 2021
commit 751c560728b1e2f6559fd6c3c7f7be756f8dae1e
20 changes: 14 additions & 6 deletions Doc/c-api/module.rst
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ state:
Example::

static PyObject*
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: static PyObject * in here.

example_call(void *)
example_call(PyObject *module)
{
return PyBytes_FromString("23");
}
Expand All @@ -613,6 +613,7 @@ state:
static PyModuleConst_Def example_constants[] = {
PyModuleConst_None("none_value"),
PyModuleConst_Long("integer", 42),
PyModuleConst_ULong("unsigned", 42UL),
PyModuleConst_Bool("false_value", 0),
PyModuleConst_Bool("true_value", 1),
#ifdef Py_MATH_PI
Expand All @@ -628,7 +629,7 @@ state:
static int
example_init_constants(PyObject *module)
{
return PyModule_AddConstants(module, posix_constants);
return PyModule_AddConstants(module, example_constants);
}

static PyModuleDef_Slot example_slots[] = {
Expand Down Expand Up @@ -667,13 +668,19 @@ state:

.. c:macro:: PyModuleConst_Long(name, value)

Add an entry for an int constant.
Add an entry for an integer constant.

.. versionadded:: 3.10

.. c:macro:: PyModuleConst_Long(name, value)

Add an entry for an unsigned integer constant.

.. versionadded:: 3.10

.. c:macro:: PyModuleConst_Bool(name, value)

Add an entry for a bool constant.
Add an entry for a bool constant. ``0`` is false, ``1`` is true.

.. versionadded:: 3.10

Expand All @@ -689,9 +696,10 @@ state:

.. versionadded:: 3.10

.. c:macro:: PyModuleConst_Call(name, c_function)
.. c:macro:: PyModuleConst_Call(name, func)

Add an entry for a constant as returned by *c_function*.
Add an entry for a constant as returned by callback with signature
``PyObject* (*func)(PyObject *module)``.

.. versionadded:: 3.10

Expand Down
34 changes: 19 additions & 15 deletions Include/moduleobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,40 +75,44 @@ typedef struct PyModuleDef_Slot{
struct PyModuleConst_Def;
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03100000
/* New in 3.10 */
enum PyModuleConst_type {
PyModuleConst_none_type = 1,
PyModuleConst_long_type = 2,
PyModuleConst_bool_type = 3,
PyModuleConst_double_type = 4,
PyModuleConst_string_type = 5,
PyModuleConst_call_type = 6,
enum _PyModuleConst_type {
_PyModuleConst_none_type = 1,
_PyModuleConst_long_type = 2,
_PyModuleConst_ulong_type = 3,
_PyModuleConst_bool_type = 4,
_PyModuleConst_double_type = 5,
_PyModuleConst_string_type = 6,
_PyModuleConst_call_type = 7,
};

typedef struct PyModuleConst_Def {
const char *name;
enum PyModuleConst_type type;
enum _PyModuleConst_type type;
union {
const char *m_str;
long m_long;
unsigned long m_ulong;
double m_double;
PyObject* (*m_call)(void);
PyObject* (*m_call)(PyObject *module);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how to make this member future-proof in term of stable ABI.

We should try to put a max_align_t inside, but this type requires C11. GCC defines it with:

typedef struct {
  long long __max_align_ll __attribute__((__aligned__(__alignof__(long long))));
  long double __max_align_ld __attribute__((__aligned__(__alignof__(long double))));
  /* _Float128 is defined as a basic type, so max_align_t must be
     sufficiently aligned for it.  This code must work in C++, so we
     use __float128 here; that is only available on some
     architectures, but only on i386 is extra alignment needed for
     __float128.  */
#ifdef __i386__
  __float128 __max_align_f128 __attribute__((__aligned__(__alignof(__float128))));
#endif
} max_align_t;

Maybe we can at least put long long and long double:

// Unused members added to make PyModuleConst_Def large enough
// to get a stable ABI and support future additions.
long long m_long_long;
long double m_long_double;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only issue I found here :)
The stable ABI doesn't have a good story around evolving structs, and I think we should design a general mechanism for that rather than try to future-proof individual structs.
To move this PR forward, could we exclude PyModule_AddConstants & co. from the limited API for the time being?

} value;
} PyModuleConst_Def;

PyAPI_FUNC(int) PyModule_AddConstants(PyObject *, PyModuleConst_Def *);

#define PyModuleConst_None(name) \
{(name), PyModuleConst_none_type, {.m_long=0}}
{(name), _PyModuleConst_none_type, {.m_long=0}}
#define PyModuleConst_Long(name, value) \
{(name), PyModuleConst_long_type, {.m_long=(value)}}
{(name), _PyModuleConst_long_type, {.m_long=(value)}}
#define PyModuleConst_ULong(name, value) \
{(name), _PyModuleConst_ulong_type, {.m_ulong=(value)}}
#define PyModuleConst_Bool(name, value) \
{(name), PyModuleConst_bool_type, {.m_long=(value)}}
{(name), _PyModuleConst_bool_type, {.m_long=(value)}}
#define PyModuleConst_Double(name, value) \
{(name), PyModuleConst_double_type, {.m_double=(value)}}
{(name), _PyModuleConst_double_type, {.m_double=(value)}}
#define PyModuleConst_String(name, value) \
{(name), PyModuleConst_string_type, {.m_string=(value)}}
{(name), _PyModuleConst_string_type, {.m_str=(value)}}
#define PyModuleConst_Call(name, value) \
{(name), PyModuleConst_call_type, {.m_call=(value)}}
{(name), _PyModuleConst_call_type, {.m_call=(value)}}

#define PyModuleConst_LongMacro(m) PyModuleConst_Long(#m, m)
#define PyModuleConst_StringMacro(m) PyModuleConst_String(#m, m)
Expand Down
4 changes: 2 additions & 2 deletions Modules/mathmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ m_inf(void)
}

static PyObject*
m_inf_o(void)
m_inf_o(PyObject *module)
{
return PyFloat_FromDouble(m_inf());
}
Expand All @@ -292,7 +292,7 @@ m_nan(void)
}

static PyObject*
m_nan_o(void)
m_nan_o(PyObject *module)
{
return PyFloat_FromDouble(m_nan());
}
Expand Down
17 changes: 10 additions & 7 deletions Objects/moduleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,24 +190,27 @@ PyModule_AddConstants(PyObject *module, PyModuleConst_Def *def)

for (cur_def = def; cur_def && cur_def->name; cur_def++) {
switch(cur_def->type) {
case PyModuleConst_none_type:
case _PyModuleConst_none_type:
v = Py_None;
Py_INCREF(v);
break;
case PyModuleConst_long_type:
case _PyModuleConst_long_type:
v = PyLong_FromLong(cur_def->value.m_long);
break;
case PyModuleConst_bool_type:
case _PyModuleConst_ulong_type:
v = PyLong_FromUnsignedLong(cur_def->value.m_ulong);
break;
case _PyModuleConst_bool_type:
v = PyBool_FromLong(cur_def->value.m_long);
break;
case PyModuleConst_double_type:
case _PyModuleConst_double_type:
v = PyFloat_FromDouble(cur_def->value.m_double);
break;
case PyModuleConst_string_type:
case _PyModuleConst_string_type:
v = PyUnicode_FromString(cur_def->value.m_str);
break;
case PyModuleConst_call_type:
v = cur_def->value.m_call();
case _PyModuleConst_call_type:
v = cur_def->value.m_call(module);
break;
default:
v = NULL;
Expand Down