CPython扩展中的全局PyObject*变量

2024-09-30 08:29:21 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python程序的一个C扩展中,我试图通过将主C函数(被调用数百万次)的两个输入设置为全局变量来提高性能,因为它们不经常更改,所以我不必一直使用lambda包装器从Python向C函数提供它们(这会浪费大量的时间)。我的代码是这样的。首先,我在文件顶部声明全局变量:

unsigned char* splitArray;
PyObject* wordCmp;

然后使用Python API函数设置它们:

^{pr2}$

在本例中,splitArray被分配给一个128个字符的数组,这个数组在splitchars_to_映射中被malloc'd,而wordCmp是一个传递给C的Python函数对象。无论如何,据我所知,char*splitArray作为一个全局变量工作得很好,但是当我后来尝试使用PyEval_CallObject调用wordCmp时,Python/C崩溃了。所以我有两个问题:

  1. 为什么当我试图在函数开头释放未初始化的指针wordCmp和splitArray时,C不会立即崩溃?在
  2. 为什么我以后不能调用wordCmp,因为我已经在堆中正确地存储了它,并将对它的引用保存为全局引用?在

Tags: 文件lambda函数代码程序声明时间浪费
1条回答
网友
1楼 · 发布于 2024-09-30 08:29:21

至于第一个问题,为什么释放未初始化的全局变量时它不会崩溃,这是因为当程序加载(guaranteed by the standard)时,全局(和静态)变量被初始化为zero,而当你用NULL(或零)调用{}时,它什么都不做。在

来自man free(1)

free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.

编辑: 你的第二个问题与你试图复制PyObject有关,你不应该这样做,因为PyObject结构可能包含指针,而且你不能进行deep复制,因为你没有访问该结构的权限,但是你应该增加引用计数并保留引用以备以后使用,请注意,当您使用O时,引用计数是从docs递增的:

O (object) [PyObject *] Store a Python object (without any conversion) in a C object pointer. The C program thus receives the actual object that was passed. The object’s reference count is not increased.

所以你应该自己增加引用,看这个example

static PyObject *my_callback = NULL;

static PyObject* my_set_callback(PyObject *dummy, PyObject *args)
{
    PyObject *result = NULL;    
    if (PyArg_ParseTuple(args, "O:set_callback", &my_callback)) {
        if (!PyCallable_Check(my_callback)) {
            PyErr_SetString(PyExc_TypeError, "parameter must be callable");
            return NULL;
        }
        Py_XINCREF(my_callback); /* Add a reference to new callback */           
        Py_INCREF(Py_None);      /* Boilerplate to return "None" */
        result = Py_None;
    }
    return result;
}

相关问题 更多 >

    热门问题