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

标签 python c pointers ctypes

我正在尝试用 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++ 中执行此操作的方法我很乐意实现该解决方案,而不是使用 ctypes 和 Python。但是,我一直没能找到一个简单的跨平台解决方案。

最佳答案

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

相反,使用 Python C API 在 C 中编写一个模块.它将公开一个函数作为开始,如下所示:

PyObject* generateReallyBigMatrix(void);

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

无论哪种方式,一旦使用适当的 API 用 C 编写此函数,您的 Python 代码就会很简单:

import foo
reallyBigMatrix = foo.generateReallyBigMatrix()

要使用 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);
}

请注意,NumPy C API 需要一个有点奇怪的 initialization ritual .另见 Numpy C API: Link several object files

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

关于Python - 使用 ctypes 在 C 和 Python 之间传递指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43162622/

相关文章:

delphi - 在德尔福/自由帕斯卡 : is ^ an operator or does it simply denote a pointer type?

python - numpy:从复杂数据类型中确定相应的 float 数据类型

python - Pytorch Softmax 给出 nans 和负值作为输出

c - 个人预处理器指令

c - 在 C 中对字符串/结构数组进行排序

c++ - 链接堆栈中的唯一指针

boost - ptr_map 和指针

python - 在 python 中绘制 3D 矩阵的最佳方法

python - 两次调用 GetListFeed 失败 (gdata.spreadsheet.service.SpreadsheetsService())

C编程十进制转二进制——递归方法中添加前导零