Hi,

I'm working on cleaning up the C API, long rationale:
https://pythoncapi.readthedocs.io/

Macros are causing multiple issues:

* They often leak "implementation details" and so are incompatible
with a stable ABI
* They have multiple pitfalls:
https://gcc.gnu.org/onlinedocs/cpp/Macro-Pitfalls.html
* They require hacks like "do { ... } while (0)" to behave properly as
a statement, otherwise they can introduce bugs
* They don't "check" argument types and their return type is often
unclear, or worse depends on the arguments type
* Variable scoping can be an issue. For example, Py_SETREF() macro in
Python 3.8 uses a "_py_tmp" variable name, rather than being able to
use a more common name like "op" or "obj".
* etc.

Static inline functions behave as regular functions: a function call
is an expression, parameter types and return type are well defined,
scoping is well defined by the C language, etc.

For backward compatibility, I kept implicit cast to PyObject* using a
macro. Example:

static inline void _Py_INCREF(PyObject *op)
{
    _Py_INC_REFTOTAL;
    op->ob_refcnt++;
}

#define Py_INCREF(op) _Py_INCREF(_PyObject_CAST(op))

Static inline functions like _Py_INCREF() are still incompatible with
a stable ABI, but it's a tradeoff between correctness and
practicability.

I wrote an article about my work on the C API in Python 3.8:
https://vstinner.github.io/split-include-directory-python38.html

--

Macros are still used for some corner cases. For example, the
following macro opens a block with { :

#define Py_BEGIN_ALLOW_THREADS { \
                        PyThreadState *_save; \
                        _save = PyEval_SaveThread();

and this one closes the block:

#define Py_END_ALLOW_THREADS    PyEval_RestoreThread(_save); \
                 }

Note also the "_save" variable which has a local scope ;-)

Another example of special macro, the following macro uses "return"
which cannot be used like that using a function:

#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None

By the way, I would prefer "return Py_GetNone()", but that's a
different discussion ;-)

--

Macros are sometimes overriden by #define, or even #undef followed by #define.

In my own projects, I prefer "const int my_constant = 123;" rather
than "#define constant 123". In Python, I'm using the status quo:
"#define constant 123".

Victor

Le mer. 4 déc. 2019 à 13:19, Skip Montanaro <skip.montan...@gmail.com> a écrit :
>
> As I wander around the code base, I keep seeing macro definitions in
> the C code. For example, there are four CALL* macros defined in
> Python/ast_opt.c which contain not entirely trivial bits of syntax.
> That code is from 2017 (as compared to, say, Modules/audioop.c, which
> first saw the light of day in 1992) I see the inline keyword used
> unconditionally in many places.
>
> I don't think stable code which uses macros should be changed (though
> I see the INCREF/DECREF macros just call private inline functions, so
> some conversion has clearly been done). Still, in new code, shouldn't
> the use of macros for more than trivial use cases (constant defs,
> simple one-liners) be discouraged at this point?
>
> Skip
> _______________________________________________
> Python-Dev mailing list -- python-dev@python.org
> To unsubscribe send an email to python-dev-le...@python.org
> https://mail.python.org/mailman3/lists/python-dev.python.org/
> Message archived at 
> https://mail.python.org/archives/list/python-dev@python.org/message/AVF6W3PMCAQK73NXOXHMHNW2KP7FJOIJ/
> Code of Conduct: http://python.org/psf/codeofconduct/



-- 
Night gathers, and now my watch begins. It shall not end until my death.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/LGORMVPTX42UIPNTG72K5BMGQTACNQ6X/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to