Как расширение C компилируется с правильным соглашением о вызовах? - PullRequest
1 голос
/ 14 апреля 2020

Предположим, что мы пишем модуль расширения CPython в C.

При определении расширения мы должны предоставить PyMODINIT_FUNC PyInit_<module_name>(void). Нигде в этом объявлении не указано собственное соглашение о вызовах.

На Linux или на Windows, как разработчик расширения может гарантировать, что функция PyInit_ скомпилирована с использованием правильного соглашения о вызовах, так что переводчик называет это успешно во время выполнения? Есть ли в заголовках Python волхвы c, которые позаботятся об этом для нас? Или что-то еще?

Тот же вопрос относится к нативным функциям, содержащимся в модуле расширения и подвергающимся Python, заключенным в объекты функций. Как мы можем гарантировать, что они скомпилированы способом, совместимым с Python соглашением о вызовах интерпретатора?

Ответы [ 2 ]

2 голосов
/ 14 апреля 2020

Соглашение о вызовах по умолчанию автоматически создается компилятором. PyMODINIT_FUNC это либо void (в Python 2), либо PyObject * (в Python 3), ничего более.

Загрузчик модулей Python dynamici c использует соглашение по умолчанию платформы (не то, что она имеет какую-либо юрисдикцию над этим; она относится к платформе).

1 голос
/ 14 апреля 2020

Вы буквально пишете PyMODINIT_FUNC PyInit_<module_name>(void). Теперь PyMODINIT_FUNC - это макрос, который распространяется на разные вещи, которые контролируются различными #ifdef s в pyport.h. В текущей редакции HEAD в редакции Github версия Python 3.9 имеет следующие 6 определений:

#define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject*
#define PyMODINIT_FUNC PyObject*
#define PyMODINIT_FUNC extern "C" Py_EXPORTED_SYMBOL PyObject*
#define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject*
#define PyMODINIT_FUNC extern "C" Py_EXPORTED_SYMBOL PyObject*
#define PyMODINIT_FUNC Py_EXPORTED_SYMBOL PyObject*

Т.е. она расширяется до PyObject * в качестве возвращаемого типа, но также extern "C", если компилируется с помощью компилятора C ++ для обеспечения связи C с этим символом и включают Py_EXPORTED_SYMBOL на некоторых платформах.

Py_EXPORTED_SYMBOL определяется в exports.h как одна из

#define Py_EXPORTED_SYMBOL __declspec(dllexport)
#define Py_EXPORTED_SYMBOL __attribute__ ((visibility ("default")))
#define Py_EXPORTED_SYMBOL

Ничто из этого не определяет соглашение о вызовах, вместо этого позволяя функции по умолчанию соответствовать соглашению cdecl, как они должны ... - также имейте в виду, что соглашения о вызовах в основном используются только в Windows.

...