我正在尝试用 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/