我试图在Python中编写一个小型的模块化程序,它将动态加载C函数并使用它们来执行计算密集型代码。在这个程序中,我创建了几个大型矩阵,我将在Python代码之间来回传递给不同的C函数。我宁愿通过引用传递这些矩阵,以避免额外的计算开销。
我已经尝试通过Python文档阅读ctypes,但它似乎并没有解释如何做到这一点。我理解,例如,我可以使用byref()或pointer()将指针从Python传递给C函数,但是如何将指针从外部C函数传递回Python?鉴于变量是Python中的名称,这是刚刚完成的#34;自动" (当缺少一个更好的术语时)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"两个运行中的函数,但使用了不同的" modifyReallyBigMatrix"运行1和运行2之间的程序。如果有一种简单的跨平台方式在C或C ++中执行此操作,我将很乐意实现该解决方案,而不是使用ctypes和Python。但是,我还没能找到一个简单的跨平台解决方案。
答案 0 :(得分:2)
您已经提到过您正在编写自己的所有代码,包括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
前缀)。