首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何将python2C扩展模块转换为python 3

如何将python2C扩展模块转换为python 3
EN

Stack Overflow用户
提问于 2019-02-03 22:31:44
回答 2查看 497关注 0票数 0

我正在试图编译一个扩展模块,其中我定义了一个自定义类型。然而,为了这个目的,我获得了一些python 2代码,但我无法将其转换为python 3模块。

到目前为止,我已经修改了我在书“python”中找到的原始代码,以便通过合并tutorial.html,但是中的一些位来尝试将其编译到python 3中,但我仍然一无所获。我知道这本书的第三版有一个python 3版本的代码,我正在试图编译,但我无法访问该版本的这本书。

下面是模块源代码test.c:

代码语言:javascript
代码运行次数:0
运行
复制
#include "Python.h"
#include "structmember.h"

/* per-instance data structure */
typedef struct {
    PyObject_HEAD
    int first, second;
} intpair;

static int
intpair_init(PyObject *self, PyObject *args, PyObject *kwds)
{
 static char* nams[] = {"first","second",NULL};
 int first, second;
 if(!PyArg_ParseTupleAndKeywords(args, kwds, "ii", nams, &first, &second))
 return -1;
 ((intpair*)self)->first = first;
 ((intpair*)self)->second = second;
 return 0;
}

static void
intpair_dealloc(PyObject *self)
{
 self->ob_type->tp_free(self);
}


static PyObject* nothing_method(PyObject* self, PyObject* args)
{
    printf("This does literally nothing!\n");

    Py_RETURN_NONE;
}

static PyMemberDef intpair_members[] = {
 {"first", T_INT, offsetof(intpair, first), 0, "first item" },
 {"second", T_INT, offsetof(intpair, second), 0, "second item" },
 {NULL}
};

static PyTypeObject t_intpair = {
 PyObject_HEAD_INIT(0) /* tp_head */
 0, /* tp_internal */
 "test.intpair", /* tp_name */
 sizeof(intpair), /* tp_basicsize */
 0, /* tp_itemsize */
 intpair_dealloc, /* tp_dealloc */
 0, /* tp_print */
 0, /* tp_getattr */
 0, /* tp_setattr */
 0, /* tp_compare */
 0, /* tp_as_number */
 0, /* tp_as_sequence */
 0, /* tp_as_mapping */
 0, /* tp_hash */
 0, /* tp_call */
 0, /* tp_str */
 PyObject_GenericGetAttr, /* tp_getattro */
 PyObject_GenericSetAttr, /* tp_setattro */
 0, /* tp_as_buffer */
 Py_TPFLAGS_DEFAULT,
 "two ints (first,second)",
 0, /* tp_traverse */
 0, /* tp_clear */
 0, /* tp_richcompare */
 0, /* tp_weaklistoffset */
 0, /* tp_iter */
 0, /* tp_iternext */
 0, /* tp_methods */
 intpair_members, /* tp_members */
 0, /* tp_getset */
  0, /* tp_base */
 0, /* tp_dict */
 0, /* tp_descr_get */
 0, /* tp_descr_set */
 0, /* tp_dictoffset */
 intpair_init, /* tp_init */
 PyType_GenericAlloc, /* tp_alloc */
 PyType_GenericNew, /* tp_new */
 PyObject_Del, /* tp_free */
};


static PyMemberDef Noddy_members[] = {
    {"PI", T_INT, 3, 0, "noddy number"},
    {NULL, NULL, 0, NULL}
};

static PyMethodDef CosMethods[] =
{
     {"does_nothing", nothing_method, METH_VARARGS, "This really does nothing"},
     {NULL, NULL, 0, NULL}
};

static PyModuleDef testmodule = {
    PyModuleDef_HEAD_INIT,
    .m_name = "test",
    .m_doc = "Example module that creates an extension type.",
    .m_size = -1,
    CosMethods,
};

PyMODINIT_FUNC
PyInit_test(void)
{
    PyObject *m;
    if (PyType_Ready(&t_intpair) < 0)
        return NULL;

    m = PyModule_Create(&testmodule);
    if (m == NULL)
        return NULL;

    Py_INCREF(&t_intpair);
    PyModule_AddObject(m, "Custom", (PyObject *) &t_intpair);
    return m;
}

文件setup.py:

代码语言:javascript
代码运行次数:0
运行
复制
from distutils.core import setup, Extension
setup(name="test", version="1.0",
      ext_modules=[
         Extension("test", ["test.c"]),
         ])

我可以使用python3 setup.py build_ext -inplace成功编译这个模块,但是,当我在python 3中导入这个模块时,会得到以下错误:

代码语言:javascript
代码运行次数:0
运行
复制
Python 3.7.2 (default, Jan 10 2019, 23:51:51) 
[GCC 8.2.1 20181127] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
SystemError: Type does not define the tp_name field.

我不理解这个错误消息,因为在tp_name PyTypeObject中定义了一个"test.intpair“字段。我在这里错过了什么?

另外,修改代码以使其为python 3编译是必要的吗?

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-02-05 18:03:52

我很确定缺陷是0, /* tp_internal */中的行:

代码语言:javascript
代码运行次数:0
运行
复制
 PyObject_HEAD_INIT(0) /* tp_head */
 0, /* tp_internal */
 "test.intpair", /* tp_name */

如果你搜索这条线,互联网上唯一提到它的就是这个问题和你使用的书--这是完全不标准的,我不知道它是从哪里来的。我怀疑Python2代码使用PyVarObject,然后使用tp_internal来填充大小,而不是PyVarObject_HEAD_INIT,但是我看不见这本书的相关页面.

类似于当前文档建议使用C99初始化。

代码语言:javascript
代码运行次数:0
运行
复制
static PyTypeObject t_intpair = {
    PyObject_HEAD_INIT(0)
    .tp_name = "test.intpair",
    // etc
 };

因此,使属性的顺序正确不再重要(您没有指定的任何内容都是0初始化的)。

构建代码提供了一些关于不匹配类型的非常清晰的警告:

warning: initialization of ‘long int’ from ‘char *’ makes integer from pointer without a cast [-Wint-conversion] "test_mod.intpair",/* tp_name */`

你应该注意这些

票数 2
EN

Stack Overflow用户

发布于 2022-09-29 20:49:06

不是直接回答你的问题,所以张贴这可能是违反网站的规则。当我寻找有关如何做类似事情的建议时,我点击这个页面,将python2 - C扩展模块转换为python3 -C。

这通常不是一个简单的工作,因为接口发生了很大的变化。我想你会发现这个链接上的资源是有帮助的:

https://docs.python.org/3/howto/cporting.html

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54508248

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档