【问题标题】:How do I use PyObject* args in C python extension?如何在 C python 扩展中使用 PyObject* args?
【发布时间】:2021-01-16 16:33:24
【问题描述】:

我正在尝试用 C 语言做一个简单的扩展,它应该能够扩展 python 代码。 我在https://github.com/munirhossain/py_c_extension找到了那个代码

#include <Python.h>

// Function 1: A simple 'hello world' function
static PyObject* helloworld(PyObject* self, PyObject* args) 
{   
    printf("Hello Munir\n");
    Py_RETURN_NONE;
    return Py_None;
}

// Function 2: A C fibonacci implementation
// this is nothing special and looks exactly
// like a normal C version of fibonacci would look
int Cfib(int n)
{
    if (n < 2)
        return n;
    else
        return Cfib(n-1)+Cfib(n-2);
}
// Our Python binding to our C function
// This will take one and only one non-keyword argument
static PyObject* fib(PyObject* self, PyObject* args)
{
    // instantiate our `n` value
    int n;
    // if our `n` value 
    if(!PyArg_ParseTuple(args, "i", &n))
        return NULL;
    // return our computed fib number
    return Py_BuildValue("i", Cfib(n));
}

// Our Module's Function Definition struct
// We require this `NULL` to signal the end of our method
// definition 
static PyMethodDef myMethods[] = {
    { "helloworld", helloworld, METH_NOARGS, "Prints Hello Munir" },
    { "fib", fib, METH_VARARGS, "Computes Fibonacci" },
    { NULL, NULL, 0, NULL }
};

// Our Module Definition struct
static struct PyModuleDef myModule = {
    PyModuleDef_HEAD_INIT,
    "myModule",
    "Test Module",
    -1,
    myMethods
};

// Initializes our module using our above struct
PyMODINIT_FUNC PyInit_myModule(void)
{
    return PyModule_Create(&myModule);
}

我想修改该代码,就像我调用 helloworld func 时一样,例如 helloworld("max") 它在 C 中返回 Hello max,但是我该如何使用 PyObject* args :/ 有什么想法我可以(在 C 中)做到这一点吗?

【问题讨论】:

    标签: c pyobject


    【解决方案1】:

    您应该阅读PyArg_ParseTuple 文档。基本上这应该工作:

    static PyObject* helloworld(PyObject* self, PyObject* args) 
    {   
        const char *name;
    
        if (!PyArg_ParseTuple(args, "s", &name)) {
            return NULL;
        }
    
        printf("Hello %s\n", name);
        Py_RETURN_NONE;
    }
    

    你需要把表中的方法定义改成

    { "helloworld", helloworld, METH_VARARGS, "Prints Hello <name>" },
    

    很自然,因为它现在需要参数。描述s 表示参数元组必须只包含一项,并且它应该是str 类型;它被转换为 UTF-8(每个 CPython 字符串对象都可以包含 UTF-8 中字符串内容的缓存副本以供 C 使用),并将指向第一个字符的指针存储到相应参数指向的指针对象中变量参数列表(即&amp;name - 输出值为const char *,对应的参数必须是指向此类对象的指针,即const char **)。

    如果PyArg_ParseTuple 返回一个假值,则表示转换失败并且设置了 Python 异常。我们通过从函数返回 NULL 而不是 Py_None 在 Python 端引发异常。

    最后,

    return Py_None; 
    

    不正确 - 在返回之前,您必须始终增加任何此类值的引用计数器 - 这就是 Py_RETURN_NONE 宏在其中所做的 - 它在功能上等同于

    Py_INCREF(Py_None);
    return Py_None;
    

    【讨论】:

      猜你喜欢
      • 2012-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-01
      • 2010-11-07
      相关资源
      最近更新 更多