代码之家  ›  专栏  ›  技术社区  ›  Carson McNeil

如何将自定义C(它本身需要特殊的链接选项来编译)与Cython链接?

  •  2
  • Carson McNeil  · 技术社区  · 12 年前

    所以我试图创建一个Cython模块,它使用我编写的.c文件。该.c文件需要一个特殊的链接选项(要编译它,我需要 gcc -o mycode mycode.c -lfftw3f ). 我可能只是在Cython中重写我的.c文件,但我想知道如何做到这一点。

    我使用的是fftw3,在编译时,您需要使用 -lfftw3f 选项除 #include <fftw3.h> 在.c文件中,如果你想使用float版本,我会这样做。

    我的 setup.py 看起来如下所示:

    from distutils.core import setup
    from distutils.extension import Extension
    from Cython.Distutils import build_ext
    
    sourcefiles = ['mycode_caller.pyx', 'mycode.c']
    
    ext_modules = [Extension("myext", sourcefiles, libraries=['fttw3f'])]
    
    setup(
      name = 'My Extension',
      cmdclass = {'build_ext': build_ext},
      ext_modules = ext_modules
    )
    

    我制作了一个名为 mycode.h 如下所示,其中包括 transform() 函数,在中定义 mycode.c :

    #include <fftw3.h>
    #include <math.h>
    
    #ifndef FOURIER_H_INCLUDED
    #define FOURIER_H_INCLUDED
    fftwf_complex** transform(float** in, int length);
    #endif
    

    还有我的Cython文件, mycode_caller.pyx 看起来是这样的:

    import numpy as np
    cimport numpy as np
    
    cdef extern from "stdlib.h":
        void free(void* ptr)
        void* malloc(size_t size)
    
    cdef extern from "fftw3.h":
        struct fftwf_complex:
            pass
    
    cdef extern from "fourier.h":
        fftwf_complex** transform(float** in_arr, int length)
    
    cdef float** npy2c_float2d(np.ndarray[float, ndim=2] a):
        cdef float** a_c = <float**>malloc(a.shape[0] * sizeof(float*))
        for k in range(a.shape[0]):
            a_c[k] = &a[k, 0]
        return a_c
    
    cpdef test_transform(data):
        nparr = np.zeros([14, 31])
        c_array = npy2c_float2d(nparr)
        ans = transform(c_array, 31)
    

    当我跑步时 python setup.py build_ext --inplace ,它构建得很好,但如果我尝试导入它,它将声明以下内容:

    ImportError: ./myext.so: undefined symbol: fftwf_execute

    此错误是由于没有 -lfftw3f公司 在编译过程中传递给gcc的选项。我该如何解决此问题?没有办法在.c源文件中指定链接器命令,对吗?我需要告诉Cython.Distutils以某种方式使用此选项吗? 谢谢你的帮助!

    编辑: 所以,我补充道 libraries=[fttw3f] 到我的 设置.py 文件,现在它在构建时抛出一个错误:

    gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro build/temp.linux-x86_64-2.7/emodsp.o build/temp.linux-x86_64-2.7/fourier.o -lfftw3f -o /home/carson/Documents/Caltech/Senior/Winter/art89/Project/openepoc/emodsp.so
    /usr/bin/ld: /usr/local/lib/libfftw3f.a(alloc.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
    /usr/local/lib/libfftw3f.a: could not read symbols: Bad value
    collect2: error: ld returned 1 exit status
    error: command 'gcc' failed with exit status 1
    
    1 回复  |  直到 12 年前
        1
  •  3
  •   nneonneo    12 年前

    只需使用 libraries 选项 Extension :

    Extension("myext", sourcefiles, libraries = ['fftw3f'], library_dirs = ['/path/to/fftw/libs'])