';进口恐怖主义';在Python扩展模块包装C库中

';进口恐怖主义';在Python扩展模块包装C库中,python,c,compilation,cython,Python,C,Compilation,Cython,(更新3包含我希望获得答案的问题。更新2指我试图理解和解决此问题所做的更正) 我试图让Python扩展模块包装一个C库(在本例中,这只是书(3er版)中描述的一个示例)。问题是我遇到了经典错误 ImportError: dynamic module does not define init function (initsample) 当我尝试导入模块时 这本书本身有如下评论: 对于下面的所有配方,假设前面的代码位于名为 sample.c中的定义可以在名为sample.h的文件中找到,并且已经

更新3包含我希望获得答案的问题。更新2指我试图理解和解决此问题所做的更正)

我试图让Python扩展模块包装一个C库(在本例中,这只是书(3er版)中描述的一个示例)。问题是我遇到了经典错误

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
文件的内容与包含书中描述的文件一致。假设所有内容都被正确复制。然后我编译
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
(最终,我复制了一个部件以清理以前的构建):

更新2

我想知道跑步后的感觉是否正常

python setup.py build_ext --inplace
文件
sample.c
将替换为cythonized版本。 我假设运行
setup.py
时使用的是
cython sample.c
,但我这样问是因为昨天我错误地编译了cython化版本
sample.c
(在删除
libsample.so
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
错误。然后我像往常一样继续:

➜ 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
这意味着我需要在环境变量LD_LIBRARY_PATH中设置当前目录。但是,我使用了一种粗糙的方法:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/Sample
正确的方法是什么?可能使用
setup.py
中的一些参数?关于我发现的几个问题,我想得到一个关于为什么会发生所有这些的答案:

  • sample.c
    在运行
    python setup.py build\u ext--inplace
    时被替换,这样可以吗
  • 每次执行此过程时是否需要还原
    sample.c
  • 我是否需要更改
    sample.pyx
    以获得正确的输出(而不是
    跳过'sample.c'Cython扩展名(最新)
    ,以获得错误的输出)
  • 解决
    导入错误的正确方法是什么:libsample.so:无法打开共享对象文件:没有这样的文件或目录
  • 添加到
    setup.py
    中是4.的一个可能选项:

    runtime_library_dirs=['./'],
    

    但是,这需要
    libsample.so
    setup.py

    位于同一目录中。请向我们显示您的
    setup.py
    文件。此外,请验证Cython是否可以在您的
    sample.pyx
    文件上工作(使用
    Cython sample.pyx
    )@Kevin谢谢。
    cython sample.pyx
    可以工作,但它替换了同一目录中的文件sample.c。我将用
    setup.py
    和?Dos更新我的问题。您的模块确实包含提到的函数
    initsample()
    ?如果没有,请再次阅读错误消息(“
    importorror:dynamic module没有定义init函数(initsample)
    ”。@RobertSmith所以您有理由:不管您是否知道,Python模块系统要求每个模块中都有这个函数:a
    PyMODINIT\u FUNC initNAME(void)
    ,其中
    NAME
    是您模块的名称。如果此函数不存在,则会出现此错误。在正确的名称下执行正确的模块初始化,则错误消失。@gl:Cython负责提供此函数;这不是OP的错误。
    ImportError: libsample.so: cannot open shared object file: No such file or directory
    
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/Sample
    
    runtime_library_dirs=['./'],