2013-02-19 27 views
1

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

我正在使用fftw3,编译时,如果您想使用浮点版本,则需要在.c文件中使用-lfftw3f选项IN 012ITION或#include <fftw3.h>

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]setup.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 

回答

3

只需使用libraries选项Extension

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

,这是很有帮助, 谢谢!但现在它引发了一个不同的错误。 – 2013-02-19 07:46:33

+0

你有共享库版本的'fftw3f',还是只有静态版本?将静态库链接到共享库有时会导致类似的问题。 – nneonneo 2013-02-19 07:51:47

+0

好吧,我安装了libfftw3-dev,现在它似乎工作。 – 2013-02-19 08:02:17