私が書いた.cファイルを使用するCythonモジュールを作成しようとしています。その .c ファイルには、特別なリンク オプションが必要です (コンパイルするには、.c ファイルが必要ですgcc -o mycode mycode.c -lfftw3f
)。Cython で .c ファイルを書き直すこともできますが、その方法を知りたいです。
私は fftw3 を使用しています。コンパイル時に、float バージョンを使用する場合は、.c ファイルで-lfftw3f
IN ADDITION オプションを使用する必要があります。#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