包含C库的Python扩展模块中的“ImportError”

时间:2015-01-04 21:26:53

标签: python c compilation cython

更新3 包含我想要获得答案的问题。更新2 是指我尝试理解并解决此问题的更正)

我正在尝试使用Python扩展模块来包装C库(在这种情况下,它只是书Python Cookbook(3er edition)中描述的一个例子。问题是我遇到了经典错误

ImportError: dynamic module does not define init function (initsample)

当我尝试导入模块时。

这本书本身有以下评论:

  

对于后面的所有配方,假设前面的代码在名为的文件中找到   sample.c,这些定义可以在名为sample.h的文件中找到,并且它已经是   堆积到库libsample中,可以链接到其他C代码。确切的细节   编译和链接因系统而异,但这不是主要关注点。   假设您使用C代码,那么您已经想到了这一点。

我认为我错了。这就是我正在做的事情:首先,我有以下文件:

➜  Sample  ls
csample.pxd  sample.c  sample.h  sample.pyx  setup.py

文件内容符合this github repository,其中包含书中描述的文件。假设一切都正确复制。然后我编译sample.c

➜  Sample  gcc -c -fPIC -I/path/to/python2.7 sample.c

这会创建sample.o,然后我继续创建一个共享库:

➜  Sample  gcc -shared sample.o -o libsample.so

创建libsample.so并最终运行setup.py文件:

➜  Sample  python setup.py build_ext --inplace 
running build_ext
skipping 'sample.c' Cython extension (up-to-date)
building 'sample' extension
creating build
creating build/temp.linux-x86_64-2.7
gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/path/to/include/python2.7 -c sample.c -o build/temp.linux-x86_64-2.7/sample.o
gcc -pthread -shared build/temp.linux-x86_64-2.7/sample.o -L. -L/path/to/lib -lsample -lpython2.7 -o /path/to/sample.so

但是,我得到了同样的错误。我错过了什么?

这是我的setup.py(最终,我复制了一个部分来清理以前的版本):

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

import sys
import os
import shutil

# clean previous build
for root, dirs, files in os.walk(".", topdown=False):
    for name in files:
        if (name.startswith("sample") and not(name.endswith(".pyx") or name.endswith(".pxd") or name.endswith(".h"))):
            os.remove(os.path.join(root, name))
    for name in dirs:
        if (name == "build"):
            shutil.rmtree(name)

ext_modules = [
Extension('sample',
    ['sample.pyx'],
    libraries=['sample'],
    library_dirs=['.'])]

setup(
    name = 'Sample extension module',
    cmdclass = {'build_ext': build_ext},
    ext_modules = ext_modules
)

更新2

我想知道运行后是否正常

python setup.py build_ext --inplace

文件sample.c被替换为cythonized版本。 我假设正在运行setup.py正在使用cython sample.c,但我问这是因为昨天我错误地编译了cythonized版本sample.c(删除libsample.so后,{{1} },sample.o在之前的运行中创建的)并且在更新sample.so之后,我收到了此错误:

sample.pyx

在此之后,我将>>> import sample Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: ./sample.so: undefined symbol: divide 恢复为原始content,删除了之前版本中的所有剩余文件(包括临时文件),而且至关重要的是,我必须以某种方式更改sample.c(例如,添加一个空行。)

我注意到我必须这样做以避免

sample.pyx

错误。然后我像往常一样继续前进:

ImportError: dynamic module does not define init function (initsample)

这次我在上面的输出中得到➜ Sample gcc -c -fPIC -I/path/to/python2.7 sample.c ➜ Sample gcc -shared sample.o -o libsample.so ➜ Sample python setup.py build_ext --inplace running build_ext cythoning sample.pyx to sample.c warning: sample.pyx:27:42: Use boundscheck(False) for faster access building 'sample' extension creating build creating build/temp.linux-x86_64-2.7 gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/path/to/include/python2.7 -c sample.c -o build/temp.linux-x86_64-2.7/sample.o gcc -pthread -shared build/temp.linux-x86_64-2.7/sample.o -L. -L/path/to/lib -lsample -lpython2.7 -o /path/to/Sample/sample.so ➜ Sample python >>> import sample Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: libsample.so: cannot open shared object file: No such file or directory 并出现新错误。但是,cythoning sample.pyx to sample.c位于libsample.so目录中。这可能是什么问题?

更新3:

我终于能够成功导入此模块,但最后一个错误

Sample

暗示我需要在环境变量LD_LIBRARY_PATH中设置当前目录。但是,我是以粗暴的方式做到的:

ImportError: libsample.so: cannot open shared object file: No such file or directory

这样做的正确方法是什么?也许在export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/Sample 中使用一些参数?关于我发现的几个问题,我想得到一个答案,为什么所有这一切都发生了:

    在运行setup.py时,
  1. sample.c会被替换。这可以吗?
  2. 我每次执行此程序时是否需要恢复python setup.py build_ext --inplace
  3. 我是否需要更改sample.c才能获得正确的输出(而不是具有误导性输出的sample.pyx
  4. 解决skipping 'sample.c' Cython extension (up-to-date)的正确方法是什么?
  5. 可能会solution添加ImportError: libsample.so: cannot open shared object file: No such file or directory

    setup.py

    但是,这需要runtime_library_dirs=['./'], libsample.so位于同一目录中。

0 个答案:

没有答案