我想从Python应用程序中调用C库.我不想包装整个API,只包含与我的案例相关的函数和数据类型.在我看来,我有三个选择:
我不确定2)或3)是否是更好的选择.3)的优点是它ctypes
是标准库的一部分,结果代码将是纯Python - 尽管我不确定这个优势实际上有多大.
两种选择都有更多优点/缺点吗?你推荐哪种方法?
编辑:感谢您的所有答案,他们为希望做类似事情的人提供了一个很好的资源.当然,这个决定仍然是针对单个案例做出的 - 没有人"这是正确的事情"的答案.对于我自己的情况,我可能会选择ctypes,但我也期待在其他项目中尝试Cython.
由于没有一个真正的答案,接受一个有点武断; 我选择了FogleBird的答案,因为它提供了对ctypes的一些很好的洞察力,它目前也是最高投票的答案.但是,我建议阅读所有答案以获得良好的概述.
再次感谢.
我知道有很多方法可以将C函数连接到Python:Python C API,scipy.weave,ctypes,pyrex/cython,SWIG,Boost.Python,Psyco ......它们最适合什么?为什么我应该使用给定的方法而不是其他方法?当我需要选择Python和C之间的绑定时应该考虑什么?
我知道有关于此的一些讨论,但它们似乎都不完整......
我知道StackOverflow上的一些问题也是相关的.例如:
我正在尝试加速我的Numpy代码,并决定我想实现一个特定的函数,我的代码大部分时间都在C中.
我实际上是C中的新手,但我设法编写了一个函数,它将矩阵中的每一行规范化为1.我可以编译它并用一些数据(在C中)测试它并且它做我想要的.那时我为自己感到骄傲.
现在我试图从Python中调用我的光荣函数,它应该接受一个2d-Numpy数组.
我尝试过的各种事情都是
痛饮
SWIG + numpy.i
ctypes的
我的功能有原型
void normalize_logspace_matrix(size_t nrow, size_t ncol, double mat[nrow][ncol]);
Run Code Online (Sandbox Code Playgroud)
因此它需要一个指向可变长度数组的指针并将其修改到位.
我尝试了以下纯SWIG接口文件:
%module c_utils
%{
extern void normalize_logspace_matrix(size_t, size_t, double mat[*][*]);
%}
extern void normalize_logspace_matrix(size_t, size_t, double** mat);
Run Code Online (Sandbox Code Playgroud)
然后我会做(在Mac OS X 64bit上):
> swig -python c-utils.i
> gcc -fPIC c-utils_wrap.c -o c-utils_wrap.o \
-I/Library/Frameworks/Python.framework/Versions/6.2/include/python2.6/ \
-L/Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/ -c
c-utils_wrap.c: In function ‘_wrap_normalize_logspace_matrix’:
c-utils_wrap.c:2867: warning: passing argument 3 of ‘normalize_logspace_matrix’ from incompatible pointer type
> g++ -dynamiclib c-utils.o -o _c_utils.so
Run Code Online (Sandbox Code Playgroud)
在Python中,我在导入模块时遇到以下错误:
>>> import c_utils
Traceback …
Run Code Online (Sandbox Code Playgroud)