使用Boost / Python的未定义符号 - 复杂

时间:2017-08-10 02:12:49

标签: python c++ boost

我想用C ++编写FFT程序代码并将其实现为python库。

所以,我使用Boost.Python 1.64并且我用C ++对FFT进行了编码:

1.fft.hpp(标题)

#ifndef _FFT_HPP_
#define _FFT_HPP_

#define BOOST_PYTHON_STATIC_LIB

#include <iostream>
#include <string>
#include <algorithm>
#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
#ifdef _OPENMP
  #include <omp.h>
#endif
#include "blas.h"
#include <complex>
#include <fftw3.h>

/* define namespace */

namespace py = boost::python;
namespace npy = boost::python::numpy;

typedef std::complex<double> dcomplex;

/* data format */

typedef struct DATA {

  /* define variable of struct */

} data;
extern data uvdata;

/* image format */

typedef struct IMAGE {

  /* define variable of struct */

} image;

/* result format */

typedef struct RESULT {

  /* define variable of struct */

} result;

/* memmory allocation of matrix and vectors */

template <typename T> T *alloc_vector(int length);
template <typename T> T *alloc_matrix(int width, int height);

/* subroutines for input data */

extern void input_pos(npy::ndarray u, npy::ndarray v, npy::ndarray uidx, npy::ndarray vidx);
extern void input_fcv(npy::ndarray uvidxfcv, npy::ndarray Vfcvr, npy::ndarray Vfcvi, npy::ndarray Varfcv);
extern void input_amp(npy::ndarray uvidxamp, npy::ndarray Vamp, npy::ndarray Varamp);
extern void input_cp(npy::ndarray uvidxcp, npy::ndarray Vcp, npy::ndarray Varcp);
extern void input_ca(npy::ndarray uvidxca, npy::ndarray Vca, npy::ndarray Varca);

/* subroutine for calculating cost */

extern void fft_test(npy::ndarray Iin, npy::ndarray x, npy::ndarray y,
                           npy::ndarray xidx, npy::ndarray yidx, int NX, int NY);

#endif // _FFT_HPP_

2.ftt.cpp(FFTW)

#include "fft.hpp"


/* redefine struct of data */

data uvdata;

template <typename T> T *transform_c_matrix(npy::ndarray matrix) {
  return reinterpret_cast<T *>(matrix.get_data());
}

void fftw_test(image *fitsimage, data *tmpdata);

void input_pos(npy::ndarray u, npy::ndarray v, npy::ndarray uidx, npy::ndarray vidx)
{
  /* input position and index of u and v to uvdata */
  uvdata.u = transform_c_matrix<double>(u);
  uvdata.v = transform_c_matrix<double>(v);
  uvdata.uidx = transform_c_matrix<int>(uidx);
  uvdata.vidx = transform_c_matrix<int>(vidx);
}

void input_fcv(npy::ndarray uvidxfcv, npy::ndarray Vfcvr, npy::ndarray Vfcvi, npy::ndarray Varfcv)
{
  /* input full-comp. visiblity to uvdata */
  /* index */
  uvdata.Nfcv = int(uvidxfcv.shape(0));
  uvdata.uvidxfcv = transform_c_matrix<int>(uvidxfcv);
  /* data and variance */
  uvdata.Vfcvr = transform_c_matrix<double>(Vfcvr);
  uvdata.Vfcvi = transform_c_matrix<double>(Vfcvi);
  uvdata.Varfcv = transform_c_matrix<double>(Varfcv);

  /* inverse flag */
  uvdata.isfcv = true;
}

void input_amp(npy::ndarray uvidxamp, npy::ndarray Vamp, npy::ndarray Varamp)
{
  /* input visibility amplitude to uvdata */
  /* index */
  uvdata.Namp = int(uvidxamp.shape(0));
  uvdata.uvidxamp = transform_c_matrix<int>(uvidxamp);
  /* data and variance */
  uvdata.Vamp = transform_c_matrix<double>(Vamp);
  uvdata.Varamp = transform_c_matrix<double>(Varamp);

  /* inverse flag */
  uvdata.isamp = true;
}

void input_cp(npy::ndarray uvidxcp, npy::ndarray Vcp, npy::ndarray Varcp)
{
  /* input closure phase to uvdata */
  /* index */
  uvdata.Ncp = int(uvidxcp.shape(0));
  uvdata.uvidxcp = transform_c_matrix<int>(uvidxcp);
  /* data and variance */
  uvdata.Vcp = transform_c_matrix<double>(Vcp);
  uvdata.Varcp = transform_c_matrix<double>(Varcp);

  /* inverse flag */
  uvdata.iscp = true;
}

void input_ca(npy::ndarray uvidxca, npy::ndarray Vca, npy::ndarray Varca)
{
  /* input closure amplitude to uvdata */
  /* index */
  uvdata.Nca = int(uvidxca.shape(0));
  uvdata.uvidxca = transform_c_matrix<int>(uvidxca);
  /* data and variance */
  uvdata.Vca = transform_c_matrix<double>(Vca);
  uvdata.Varca = transform_c_matrix<double>(Varca);

  /* inverse flag */
  uvdata.isca = true;
}

void fft_test(npy::ndarray Iin, npy::ndarray x, npy::ndarray y,
  npy::ndarray xidx, npy::ndarray yidx, int NX, int NY)
{
  data tmpdata;
  image fitsimage;

  /* input initial image */
  fitsimage.Iin = transform_c_matrix<double>(Iin);
  fitsimage.x = transform_c_matrix<double>(x);
  fitsimage.y = transform_c_matrix<double>(y);
  fitsimage.xidx = transform_c_matrix<int>(xidx);
  fitsimage.yidx = transform_c_matrix<int>(yidx);
  fitsimage.NX = NX;
  fitsimage.NY = NY;
  fitsimage.Npix = NX*NY;

  uvdata.NU = NX/2+1;
  uvdata.NV = NY;
  uvdata.Nuv = uvdata.NU*uvdata.NV;

  tmpdata = uvdata;
  fftw(&fitsimage, &tmpdata);
}

void fftw(image *fitsimage, data *tmpdata)
{
  int iuv,inc=1;
  double *in,*Vreal,*Vimag;
  dcomplex *out;
  fftw_plan fftplan;

  in = alloc_matrix<double>(fitsimage->NX,fitsimage->NY);
  out = alloc_matrix<dcomplex>(tmpdata->NU,tmpdata->NV);
  Vreal = alloc_matrix<double>(tmpdata->NU,tmpdata->NV);
  Vimag = alloc_matrix<double>(tmpdata->NU,tmpdata->NV);

  fftplan = fftw_plan_dft_r2c_2d(fitsimage->NX, fitsimage->NY, 
                             in, reinterpret_cast<fftw_complex*>(out), FFTW_MEASURE);

  dcopy_(&(fitsimage->Npix), fitsimage->Iin, &inc, in, &inc);
  fftw_execute(fftplan);

  for (iuv=0; iuv<tmpdata->Nuv; ++iuv) {
    Vreal[iuv] = std::real(out[iuv]);
    Vimag[iuv] = std::imag(out[iuv]);
    printf("%d %f\n",iuv,Vreal[iuv]);
  }

  delete[] in;
  delete[] out;
  fftw_destroy_plan(fftplan);
}

3.fft_tools.cpp(用于FFT的工具)

#include "fft.hpp"


template <typename T> T *alloc_vector(int length) {
  return new T[length];
}

template <typename T> T *alloc_matrix(int width, int height) {
  return new T[width*height];
}

4.libfftw.cpp(python的实现)

#include "fft.hpp"


BOOST_PYTHON_MODULE(libfft)
{
  Py_Initialize();
  npy::initialize();

  py::def("input_pos", &input_pos);
  py::def("input_fcv", &input_fcv);
  py::def("input_amp", &input_amp);
  py::def("input_cp", &input_cp);
  py::def("input_ca", &input_ca);
  py::def("fft_test", &fft_test);
}

我已使用以下方式遵守此规定:

g++ -fPIC -Wall -O2 -lopenblas -fftw3 -lboost_python -lboost_numpy -I/usr/include/python2.7 -shared -o libfft.so fft.cpp fft_tools.cpp libfftw.cpp

导入时出现以下错误:

import libfft
ImportError: ./libfft.sp: undefined symbol: _Z12alloc_matrixISt7complexIdEEPT_ii

这是什么意思,我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

链接代码时,链接器无法找到符号alloc_matrix<complex>。这是因为您已将其实现放在.cpp文件中,而不是.hpp文件中。如果你:

  • 将您的实施移出fft_tools.cpp,并将其放入fft.hpp
  • 现在完全摆脱fft_tools.cpp文件,它是空的。

然后你会发现这个特定的链接错误会消失。