2016-04-27 70 views
1

,當我創造了在Python中使用使用痛飲* .so文件,但是當我導入它,我得到這個:「未定義的符號」錯誤導入痛飲+ Python模塊

/_analyzer.so: undefined symbol: autocorellation 

我就照幾乎一切此指令:https://scipy.github.io/old-wiki/pages/Cookbook/SWIG_NumPy_examples.html

我的代碼如下:

analyzer.h:

void autocorellation(double *in, double *out, long long n); 

analyzer.cpp:

#include "analyzer.h" 
#include <math.h> 
#include <stdlib.h> 

#define PI 3.14159265358979323846 

typedef struct { 
    double real; 
    double im; 
} Complex; 

void complex_multiply(Complex a,Complex b,Complex* c){ 
    c->real = a.real * b.real - a.im * b.im; 
    c->im = a.real * b.im + a.im * b.real; 
} 

void complex_multiply_int(int a, Complex b,Complex* c){ 
    c->real = a * b.real; 
    c->im = a * b.im; 
} 

void complex_sum(Complex a,Complex b,Complex* c){ 
    c->real = a.real + b.real; 
    c->im = a.im + b.im; 
} 

void complex_conjugate(Complex* a,Complex* b,long long n){ 
    for(int i = 0; i < n; ++i){ 
     b[i].real = a[i].real; 
     b[i].im = -1 * a[i].im; 
    } 
} 

long long rev (long long num, long long lg_n) { 
    long long res = 0; 
    for (long long i=0; i < lg_n; ++i) 
     if (num & (1 << i)) 
      res |= 1 << (lg_n-1-i); 
    return res; 
} 

void fft (Complex* a, long long n,bool invert) { 
    long long lg_n = 0; 
    while ((1 << lg_n) < n) 
     ++lg_n; 
    for (long long i=0; i<n; ++i){ 
     long long r= rev(i,lg_n); 
     if (i < r){ 
      a[i].real = a[i].real + a[r].real; 
      a[r].real = a[i].real - a[r].real; 
      a[i].real = a[i].real - a[r].real; 
      a[i].im = a[i].im + a[r].im; 
      a[r].im = a[i].im - a[r].im; 
      a[i].im = a[i].im - a[r].im; 
     } 
    } 
    for (long long len=2; len<=n; len <<= 1) { 
     double ang = 2*PI/len * (invert ? -1 : 1); 
     Complex wn; 
     wn.real = cos(ang); 
     wn.im = sin(ang); 
     for (long long i=0; i<n; i+=len) { 
      Complex w; 
      w.real = 1; 
      w.im = 0; 
      long long ll = (long long)(len * 0.5); 
      for (long long j=0; j< ll; ++j) { 
       Complex u = a[i+j],v; 
       complex_multiply(a[i+j+ll],w,&v); 
       complex_sum(u,v,&a[i+j]); 
       complex_multiply_int(-1,v,&v); 
       complex_sum(u,v,&a[i+j+ll]); 
       complex_multiply(w,wn,&w); 
      } 
     } 
    } 
    if (invert) 
     for (long long i=0; i<n; ++i){ 
      a[i].real /= n; 
      a[i].im /= n; 
     } 
} 

void autocorellation(double *in, double *out, long long n){ 
    long long le = 1; 
    while(n > le) 
     le *= 2; 
    double m = 0; 
    for(int i = 0; i < n; ++i) 
     m+=in[i]; 
    m /= n; 
    for(int i = 0; i < n; ++i) 
     in[i] -= m; 
    Complex* a = (Complex*) malloc(le*sizeof(Complex)); 
    Complex* b = (Complex*) malloc(le*sizeof(Complex)); 
    for(long long i = 0; i < n; ++i){ 
     a[i].im = 0; 
     a[i].real = in[i]; 
    } 
    for(long long i = n; i < le; ++i){ 
     a[i].im = 0; 
     a[i].real = 0; 
    } 
    fft(a,le,false); 
    complex_conjugate(a,b,le); 
    Complex* c = (Complex*) malloc(le*sizeof(Complex)); 
    for(long long i = 0; i < le; ++i) 
     complex_multiply(b[i],a[i],&c[i]); 
    fft(c,le,true); 
    for(long long i = 0; i < n; ++i) 
     out[i] = (c[i].real/c[0].real); 
    free(a); 
    free(b); 
    free(c); 
} 

analyzer.i:

%module analyzer 

%{ 
    #define SWIG_FILE_WITH_INIT 
    #include "analyzer.h" 
%} 

%include "numpy.i" 

%init %{ 
    import_array(); 
%} 

%apply (double* IN_ARRAY1,int DIM1) {(double *in, long long n)} 
%apply (double* ARGOUT_ARRAY1,int DIM1) {(double *out, long long n)} 
%include "analyzer.h" 

setup.py:

#! /usr/bin/env python 

# System imports 
from distutils.core import * 
from distutils  import sysconfig 

# Third-party modules - we depend on numpy for everything 
import numpy 

# Obtain the numpy include directory. This logic works across numpy versions. 
try: 
    numpy_include = numpy.get_include() 
except AttributeError: 
    numpy_include = numpy.get_numpy_include() 

# ezrange extension module 
_analyzer = Extension("_analyzer", 
        ["analyzer.i","analyzer.cpp"], 
        include_dirs = [numpy_include], 
        ) 

# ezrange setup 
setup( name  = "range function", 
     description = "Autocorellation function evaluation", 
     author  = "Bodya", 
     version  = "1.0", 
     ext_modules = [_analyzer] 
     ) 

回答

0

您的代碼和食譜示例之間的區別是,您的代碼是C++。因此,您需要將-c++選項傳遞給SWIG。在setup.py中構建Extension(...),只需添加swig_opts=['-c++'],即可。

請注意,distutils仍然會在生成的包裝文件上調用C編譯器,但是這將具有.cpp擴展名,所以如果編譯器爲gcc或clang,應該編譯正確。

我的經驗使用distutils或setuptools的C++ SWIG擴展,甚至略微超越平凡已經很差,所以我調用SWIG生成distutils外的包裝(我通過Makefile執行),只使用distutils編譯來自包裝文件的擴展。

+0

明白了,非常感謝) – Hi4ko

相關問題