如何为C函数使用LAPACK库的Python编译C扩展?

2024-06-25 22:41:10 发布

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

我为Python编写了一个C extesion,模块成功地编译在一个.so文件中。但是,当我尝试在Python端使用wrapped C函数(Python中调用包装的C函数的测试代码)时,我得到了以下ImportError

ImportError: /home/username/newModule.cpython-36m-x86_64-linux-gnu.so: undefined symbol: dgetri_

{cd4{I>在cd4{3>库中查找到的链接{cd3>是错误的。所以我的问题是:

当包装好的c函数依赖LAPACK库生成.so格式的模块时,如何为python编译c扩展代码?

{I}当前正在编译python模块。我想我需要从命令行编译C代码以链接LAPACK,但不确切地知道哪些命令是合适的?在

感谢任何帮助。在


Tags: 模块文件函数代码homeso链接username
2条回答

另外,我在linux中编译时使用了以下两行代码

$gcc -DNDEBUG -Wall -Wstrict-prototypes -fPIC -I/home/username/anaconda3/include/python3.6m -c stackDoc.cpp -o mydemo.o
$gcc -shared mydemo.o -o mydemo.so

我发现下面的链接很有用, https://docs.python.org/2/extending/building.html

您可能对使用scipy.linalg.cython_lapack感兴趣。 它提供对LAPACK函数^{}的访问。而the good news是:

This makes it possible to use SciPy's BLAS and LAPACK from any 3rd party Cython module without explicitely linking with the libraries. This means that projects like scikit-learn and statsmodels do not need to maintain a separate build dependency on BLAS and LAPACK.

使用dger的示例在Calling BLAS / LAPACK directly using the SciPy interface and Cython上提供。另请参见Improving Cython Lapack performance with internal array definitions? 在我对MPI python-Open-MPI的回答中,我详细介绍了如何使用cythonãblas,因此下面是如何将其改编为dgetri的方法:

  1. 代码的关键部分写在^{},在一个专用文件myinverse.pyx中。

  2. 这个文件被Cython转换成myinverse.c文件

  3. 这个c文件是由您最喜欢的c编译器gcc编译来构建一个共享库myinverse.so

  4. 优化后的函数可以在程序中使用import myinverse

下面是一个cython模块,它将放在.pyx文件中:

import numpy

cimport numpy
cimport scipy.linalg.cython_lapack
ctypedef numpy.float64_t DTYPE_t
cimport cython
from libc.stdlib cimport malloc, free

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def invert(numpy.ndarray[DTYPE_t, ndim=2] array):

    cdef  int rows = array.shape[0]
    cdef   int cols = array.shape[1]
    cdef  int info = 0
    if cols !=rows:
        return array,1,"not a square matrix"

    cdef int* ipiv = <int *> malloc(rows * sizeof(int))
    if not ipiv:
        raise MemoryError()

    scipy.linalg.cython_lapack.dgetrf(&cols,&rows,&array[0,0],&rows,ipiv,&info)
    if info !=0:
        free(ipiv)
        return array,info,"dgetrf failed, INFO="+str(info)
    #workspace query
    cdef double workl
    cdef int lwork=-1
    scipy.linalg.cython_lapack.dgetri(&cols,&array[0,0],&rows,ipiv,&workl,&lwork,&info)
    if info !=0:
        free(ipiv)
        return array,info,"dgetri failed, workspace query, INFO="+str(info)
    #allocation workspace
    lwork= int(workl)
    cdef double* work = <double *> malloc(lwork * sizeof(double))
    if not work:
        raise MemoryError()

    scipy.linalg.cython_lapack.dgetri(&cols,&array[0,0],&rows,ipiv,work,&lwork,&info)
    if info !=0:
        free(ipiv)
        free(work)
        return array,info,"dgetri failed, INFO="+str(info)

    free(ipiv)
    free(work)

    return array,info,""

要对.pyx文件进行cythonize和编译,可以使用以下makefile(我希望您使用的是Linux…)

^{pr2}$

新的python myinverse函数chainng LAPACK的dgetrf()和{},在python主文件中调用:

^{3}$

相关问题 更多 >