如何从C++创建一个c_void_p PyObject,将其传递给Python并将其重新获取回C++

3

我需要将在C++中创建的ArrayFire数组共享给Python。这个过程可以正常工作:

PyObject* arrayToPyObject(const af::array& arr)
{
    // Create arrayfire array and set 
    PyObject* afArray = createObject("arrayfire", "Array");

    PyObject* ctypes_mod = PyImport_ImportModule("ctypes");
    PyObject* c_void_p = PyObject_GetAttrString(ctypes_mod, "c_void_p");
    PyObject* p = PyObject_CallFunction(c_void_p, "O", PyLong_FromVoidPtr(arr.get()));

    if (PyObject_SetAttr(afArray, PyUnicode_FromString("arr"), p) == 0)
    {
        return afArray;
    }
    else
    {
        Py_XDECREF(afArray);
        return nullptr;
    }
}

现在,如果我的Python脚本返回一个ArrayFire数组,我需要读取arr属性并获取指针,然后将其分配给C++数组。
af::array pyObjectToArray(PyObject* obj)
{
    af::array tmp;
    PyObject* arr = PyObject_GetAttr(obj, PyUnicode_FromString("arr"));
    if (arr)
    {
        af_array ref = (af_array)(PyLong_AsVoidPtr(arr));

        if (ref)
        {
            tmp.set(ref);
        }
    }

    return tmp;
}

问题在于PyLong_AsVoidPtr失败,出现了“TypeError”类:需要整数。 ctypes文档(16.16.1.4.基本数据类型)指出c_void_p的Python类型为int或None。显然,在我的情况下它是None。
如何使用C API将c_void_p转换为Python?
谢谢!

好奇,你为什么不使用ArrayFire的Python封装器? - Pavan Yalamanchili
我正在使用它。但是,如果您需要共享在应用程序中创建的af::array到arrayfire Python绑定类型Array中,则需要进行诡计处理。通过传递af_array ref的好处是,如果您正在使用CUDA后端,则内存保留在GPU中,因此您不会从复制数据中获得开销。 - Damien LEFEVRE
1个回答

2

我解决了它。

ctypes类型对象的值可以从value属性中读取。

af::array pyObjectToArray(PyObject* obj)
{
    af::array tmp;
    PyObject* arr = PyObject_GetAttr(obj, PyUnicode_FromString("arr")); // <-- c_void_p object
    PyObject* p = PyObject_GetAttr(arr, PyUnicode_FromString("value") // <-- int value

    if (arr)
    {
        af_array ref = (af_array)(PyLong_AsVoidPtr(p));

        if (ref)
        {
            tmp.set(ref);
        }
    }

    return tmp;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接