如何使用正确的本机调用约定编译 C 扩展?
How is a C extension compiled with the correct native calling convention?
假设我们正在用 C 编写一个 CPython 扩展模块。
定义扩展时,我们需要提供一个PyMODINIT_FUNC PyInit_<module_name>(void)
。此声明中未指定本机调用约定。
无论是 Linux 还是 Windows,扩展开发人员如何确保 PyInit_
函数使用正确的调用约定进行编译,以便解释器在期间成功调用它运行? Python headers 中有什么魔法可以帮我们解决这个问题吗?或者别的什么?
同样的问题也适用于扩展模块中包含的本机函数,并暴露给包装为函数 objects 的 Python。我们如何确保以与 Python 解释器调用约定兼容的方式编译它们?
默认调用约定由编译器自动制定。 PyMODINIT_FUNC
是 void
(在 Python 2 中)或 PyObject *
(在 Python 3 中),仅此而已。
Python 动态模块加载器使用平台的默认约定(并不是说它对此有任何管辖权;它属于平台)。
您实际上是在写 PyMODINIT_FUNC PyInit_<module_name>(void)
。现在 PyMODINIT_FUNC
是一个宏,可以扩展到由 pyport.h
中的各种 #ifdef
控制的不同事物。在 Github 修订 Python 3.9 开发版本中的当前 HEAD 修订中有这 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 *
作为 return 类型,但如果使用 C++ 编译器编译以确保针对此符号的 C 链接,它也扩展为 extern "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
None 其中指定了调用约定,而不是让函数默认为 cdecl 约定,因为它们应该... - 还请注意,调用约定大多只在 Windows 中.
假设我们正在用 C 编写一个 CPython 扩展模块。
定义扩展时,我们需要提供一个PyMODINIT_FUNC PyInit_<module_name>(void)
。此声明中未指定本机调用约定。
无论是 Linux 还是 Windows,扩展开发人员如何确保 PyInit_
函数使用正确的调用约定进行编译,以便解释器在期间成功调用它运行? Python headers 中有什么魔法可以帮我们解决这个问题吗?或者别的什么?
同样的问题也适用于扩展模块中包含的本机函数,并暴露给包装为函数 objects 的 Python。我们如何确保以与 Python 解释器调用约定兼容的方式编译它们?
默认调用约定由编译器自动制定。 PyMODINIT_FUNC
是 void
(在 Python 2 中)或 PyObject *
(在 Python 3 中),仅此而已。
Python 动态模块加载器使用平台的默认约定(并不是说它对此有任何管辖权;它属于平台)。
您实际上是在写 PyMODINIT_FUNC PyInit_<module_name>(void)
。现在 PyMODINIT_FUNC
是一个宏,可以扩展到由 pyport.h
中的各种 #ifdef
控制的不同事物。在 Github 修订 Python 3.9 开发版本中的当前 HEAD 修订中有这 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 *
作为 return 类型,但如果使用 C++ 编译器编译以确保针对此符号的 C 链接,它也扩展为 extern "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
None 其中指定了调用约定,而不是让函数默认为 cdecl 约定,因为它们应该... - 还请注意,调用约定大多只在 Windows 中.