在 C 和 Python 之间传递的 C 指针(使用胶囊)为空

A C pointer passed between C and Python (using capsule) is empty

我正在为我开发的一些 C 函数创建一个 python 扩展。

该代码使用了我们不需要从 python 代码中分析的复杂结构,因此我们使用指针胶囊将结构从一个函数传递到另一个函数。

这是我在 C 中创建的 python 扩展的简化(这里我只使用双精度而不是我们的结构):

#include "Python.h"

static PyObject *example2 (PyObject *dummy, PyObject *args)
{
    PyObject *pymodel=NULL;

    if (!PyArg_ParseTuple(args, "O", &pymodel))
    return NULL;

    double *numero;
    if (!(numero = (double*) PyCapsule_GetPointer(pymodel, "DOUBLE"))) {
        return NULL;
    }

    printf("Pointer %x and value %f\n",numero,*numero);

    return Py_BuildValue("");
}

static PyObject* example (PyObject *dummy, PyObject *args)
{
    double *numero;
    double valnum = 6.0;
    numero = &valnum;

    printf("Pointer %x and value %f\n",numero,*numero);
    PyObject * ret = PyCapsule_New(numero, "DOUBLE", NULL);

    return ret;
}

/* Module method table */
static PyMethodDef LIBIRWLSMethods[] = {
    {"example", example, METH_VARARGS, "descript of example"},
    {"example2", example2, METH_VARARGS, "prediction using a trained model"},
    { NULL, NULL, 0, NULL}
};

/* module initialization */
PyMODINIT_FUNC initLIBIRWLS(void)
{
    (void) Py_InitModule("LIBIRWLS", LIBIRWLSMethods);
}

使用 setup.py 文件安装此扩展后,我们调用 python:

中的函数
import LIBIRWLS

myCapsule = LIBIRWLS.example()
LIBIRWLS.example2(myCalsule)

这是 运行 python 代码后的标准输出:

Pointer b9c27b58 and value 6.000000
Pointer b9c27b58 and value 0.000000

指针地址已正确传递,但它丢失了值,我们不知道原因。

您正在尝试传递指向堆栈上某个值的指针。请参阅 this question 了解为什么这是个坏主意。要传递指针,您需要从堆中分配内存:

static PyObject *example2 (PyObject *dummy, PyObject *args)
{
    PyObject *pymodel = NULL;
    if (!PyArg_ParseTuple(args, "O", &pymodel))
        return NULL;

    double *numero;
    if (!(numero = (double*) PyCapsule_GetPointer(pymodel, "DOUBLE")))
        return NULL;

    printf("Pointer %p and value %f\n", numero, *numero);

    return Py_BuildValue("");
}

static PyObject* example (PyObject *dummy, PyObject *args)
{
    double *numero = (double *) PyMem_Malloc(sizeof(double *));
    if (NULL == numero)
        return NULL;
    *numero = 6.0;

    printf("Pointer %p and value %f\n", numero, *numero);

    PyObject * ret = PyCapsule_New(numero, "DOUBLE", NULL);
    return ret;
}

输出

Pointer 0x7f9103d173f0 and value 6.000000
Pointer 0x7f9103d173f0 and value 6.000000