链接共享库的Cython错误?

时间:2018-04-06 16:21:21

标签: cython linker-errors dynamic-linking

我尝试使用Cuhre库中提供的Cuba例程。我以前遇到过将静态库链接到Cython的错误,因此我尝试使用Cuhre属性创建共享库。为此,我有三个文件:cuhre.c, cuhre.h, and libcuhre.so(通过编译cuhre.c创建)。

cuhre.c有一个例程tryCuhre,它基本上调用古巴图书馆提供的Cuhre路由。为简单起见,它仅适用于2D集成:

double tryCuhre(integrand_t t, void * ud)
{
  int comp, nregions, neval, fail;
  cubareal integral[NCOMP], error[NCOMP], prob[NCOMP];
  Cuhre(2, 1, t, ud, 1,
    EPSREL, EPSABS, VERBOSE | LAST,
    MINEVAL, MAXEVAL, 13,
    STATEFILE, SPIN,
    &nregions, &neval, &fail, integral, error, prob);
  return (double)integral[0];
}

所有大写字母中的变量(例如MINEVAL和SPIN)都是在编译时预定义的并且是常量。

这是我的cuhre.h文件,由cuhre.c包含:

#ifndef CUHRE_H_
#define CUHRE_H_


#ifdef __cplusplus
extern "C" {
#endif
typedef double cubareal;
typedef int (*integrand_t)(const int *ndim, const cubareal x[], const int 
*ncomp, cubareal f[], void *userdata);

double tryCuhre(integrand_t t, void * ud);
#ifdef __cplusplus
}
#endif
#endif

运行命令集后

gcc -Wall -fPIC -c cuhre.c
gcc -shared -o libcuhre.so cuhre.o

我可以创建共享库libcuhre.so。到现在为止还挺好。应该注意的是,到目前为止,例程正常工作,即使cuhre.c中的可执行文件正确执行。

我正在尝试使用tryCuhre文件中的cython例程(execute.pyx)。在顶部,我有声明:

cdef extern from "math.h":
    double sin(double x)
    double cos(double x)
    double sqrt(double x)
    double atan(double x)
    double exp(double x)
    double log(double x)

cdef extern from "cuhre.h":
    ctypedef double cubareal
    ctypedef int (*integrand_t)(const int *ndim, const cubareal x[], const int *ncomp, cubareal f[], void *userdata)
    double tryCuhre(integrand_t t, void * ud)

最后,为了编译,我正在使用命令

python setup.py build_ext --inplace

在setup.py上,如下所示:

from distutils.core import setup, Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize
from distutils.extension import Extension

sourcefiles = ['execute.pyx']
ext_modules = [Extension("execute", sourcefiles, library_dirs = 
['~/Documents/project/libcuhre.so'],)]

setup(
  name = 'execute',
  cmdclass = {'build_ext': build_ext},
  ext_modules = ext_modules
)

编译文件。但是,每当我尝试声明时

import execute
在python shell中,它引发了错误:

/Documents/project/execute.so: undefined symbol: tryCuhre

我已经四处寻找链接我人工创建的libcuhre.so库的方法,但到目前为止还没有工作。如何解决这个问题?为什么我的程序如何能够从数学库中找到所有方法(sin,cos,exp等),而不是我的libcuhre.so中的任何方法? (还应注意,所有这些文件都在同一目录~/Documents/project。)

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

依赖的源代码和库需要包含在Extension中,作为libraries链接,或源文件进行编译。

library_dirs仅添加到链接器将搜索库的目录,但不链接任何内容,因此是不够的。

在这种情况下,由于C代码是自构建的并且是单个.c,因此最简单的方法是将它们一起编译为源代码。这也意味着cuhre.c将由setuptools本身编译,自动编译目标分发。

from setuptools import setup, Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize

sourcefiles = ['execute.pyx', 'cuhre.c']
ext_modules = [Extension("execute", sourcefiles,
    include_dirs=['.'],
    depends='cuhre.h',
)]
setup(
  name='execute',
  cmdclass = {'build_ext': build_ext},
  ext_modules = ext_modules
)

代码也更改为使用setuptoolsdistutils已弃用,现在已成为setuptools的一部分。