Python在C和Python之间使用cytype传递指针

2024-09-21 00:45:38 发布

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

我试图用Python编写一个小型的模块化程序,它将动态加载C函数并使用它们来执行计算密集型代码。在这个程序中,我创建了两个大矩阵,我将在Python代码之间来回传递给不同的C函数。为了避免这些额外的计算开销,我宁愿传递这些矩阵。在

我试过阅读ctypes的Python文档,但它似乎没有解释如何做到这一点。例如,我知道可以使用byref()或pointer()将指针从Python传递到C函数,但是如何将指针从外部C函数传递回Python呢?假设变量在Python中是名称,那么当Python从C函数接收值时,这是否只是“自动”完成的(因为缺少更好的术语)?在

作为一个具体的例子,这就是我要做的(在伪代码中):

foo = ctypes.CDLL("pathToFoo")
bar = ctypes.CDLL("pathToBar")

# Generate a large matrix by calling a C function.
reallyBigMatrix = foo.generateReallyBigMatrix()

# Pass reallyBigMatrix to another function and perform some operation
# on it. Since the matrix is really big, I would prefer to pass a 
# reference to this matrix to my next C function rather than passing
# the matrix by value.
modifiedReallyBigMatrix = bar.modifyReallyBigMatrix(reallBigMatrix)

或者,我将Python和C结合使用,因为我需要一种在程序中动态加载C函数的简单方法。我可以将不同C文件的路径传递给Python程序,这样Python程序将在不同的函数上执行相同的代码。例如,我可能希望以两种不同的方式运行我的程序:在两次运行中保持相同的“generateReallyBigMatrix”函数,但在运行1和运行2之间使用了不同的“modifyReallyBigMatrix”程序。如果在C或C++中有一个简单的跨平台的方法来实现这一点,我将很乐意实现这个解决方案而不是使用cType和Python。然而,我还没有找到一个简单的、跨平台的解决方案。在


Tags: to函数代码程序byfoobar动态
1条回答
网友
1楼 · 发布于 2024-09-21 00:45:38

您已经提到,所有代码都是您自己编写的,包括Python和C。我建议不要为此使用ctypes,因为ctypes最适合使用不能修改的C库。在

相反,使用Python C API在C中编写一个模块。它将首先公开一个函数,如下所示:

PyObject* generateReallyBigMatrix(void);

现在,您不必尝试返回原始C指针,而是可以返回任何您喜欢的Python对象。这里的好选择是返回一个NumPy数组(使用NumPy C API),或者返回一个Python "buffer"(如果需要,可以从中用Python构造NumPy数组)。在

不管怎样,一旦使用适当的api用C编写了这个函数,Python代码就会很简单:

^{pr2}$

要使用NumPy C API执行此操作,您的C代码如下所示:

PyObject* generateReallyBigMatrix(void)
{
    npy_intp dimension = 100;
    PyArray_Descr* descr;
    PyArray_DescrAlignConverter2("float64", &descr); // use any dtype

    PyObject* array = PyArray_Empty(1, &dimension, descr, 0/*fortran*/);
    Py_DECREF(descr);

    void* data = PyArray_DATA(array);
    // TODO: populate data

    return array;
}

static PyMethodDef methods[] = {
    {"generateReallyBigMatrix", generateReallyBigMatrix, METH_VARARGS, "doc"},
    {NULL, NULL, 0, NULL}        /* Sentinel */
};

PyMODINIT_FUNC initfoo(void)
{
    import_array(); // enable NumPy C API
    Py_InitModule("foo", methods);
}

注意,numpycapi需要一个稍微奇怪的initialization ritual。另请参见Numpy C API: Link several object files

然后将代码编译为一个名为foo.so(没有lib前缀)的共享库。在

相关问题 更多 >

    热门问题