编译Python 3.x的C模块时PY_MAJOR_VERSION未定义

1 投票
1 回答
2201 浏览
提问于 2025-04-16 08:01

我正在尝试升级一个小的C模块,让它能在Python 3.x上运行,但在编译时遇到了一些麻烦。现在我最大的障碍是,我应该用来检查Python版本的预处理器定义没有起作用。

这个模块目前包含两个.c文件(我暂时把其他的注释掉了)。在这两个文件中,PY_MAJOR_VERSION没有定义,所以编译器无法在需要的地方使用Python 3.x特有的定义。

mymodule.c:

#ifndef PY_MAJOR_VERSION
#error Major version not defined!
#endif

#if PY_MAJOR_VERSION >= 3
#define PY3K
#endif

#include "Python.h"
#include "myobj.h"

/* omitted: irrelevant boilerplate structs */

PyMODINIT_FUNC
initmymodule(void)
{
    PyObject* m;

#ifdef PY3K
    m = PyModule_Create(&mymodule_struct);
#else
    (void) Py_InitModule("mymodule", MyModMethods);
    m = Py_InitModule3("mymodule", NULL,
               "My Module");
#endif

    /* omitted: the rest of the module init code */
}

myobj.c:

#ifndef PY_MAJOR_VERSION
#error Major version not defined!
#endif

#if PY_MAJOR_VERSION >= 3
#define PY3K
#endif

#include "Python.h"
#define NEED_STATIC
#include "myobj.h"
#undef NEED_STATIC

#ifdef PY3K
#define PYSTR_FROMC PyUnicode_FromString
#define PYSTR_FORMAT PyUnicode_Format
#define PYINT_FROMC PyLong_FromLong
#else
#define PYSTR_FROMC PyString_FromString
#define PYSTR_FORMAT PyString_Format
#define PYINT_FROMC PyInt_FromLong
#endif

/* omitted: rest of module code */

setup.py:

from distutils.core import setup, Extension

module1 = Extension('mymodule', sources = ['mymodule.c', 'myobj.c'])
setup(name='mymodule', version='0.1', ext_modules=[module1])

我使用 c:\python31\python setup.py bdist_wininst 来构建这个模块。

PY_MAJOR_VERSION应该在哪里定义呢?这是我需要告诉distutils去传递给编译器的东西吗?

1 个回答

8

我找到了我之前犯的错误。是因为 Python.h 文件里定义了 PY_MAJOR_VERSION。由于我把我的 #defines 放在了 #includes 之前,所以我错过了这个定义。我也不知道我当时为什么会觉得构建系统会为我定义这个...

把 #if PY_MAJOR_VERSION >= 3 移到 #include "Python.h" 之后执行,这样就解决了问题。我把这个留在这里,以防其他人和我一样傻,因为在谷歌上找这个问题时没有找到有用的信息。

撰写回答