【问题标题】:A C pointer passed between C and Python (using capsule) is empty在 C 和 Python 之间传递的 C 指针(使用胶囊)为空
【发布时间】:2017-03-03 04:11:37
【问题描述】:

我正在为我开发的一些 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

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

【问题讨论】:

    标签: python c pointers wrapper encapsulation


    【解决方案1】:

    您正试图传递一个指向堆栈上的值的指针。请参阅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
    

    【讨论】:

    • 成功了。这是我的第一个 python 扩展(我正在为我的 phd 代码创建包装器),我完全迷失了。
    • 我曾经为 Matlab 编写 cmex 扩展,所以这对我来说很熟悉。
    猜你喜欢
    • 1970-01-01
    • 2019-11-13
    • 2012-01-16
    • 2011-09-26
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多