【问题标题】:Using Cython To Link Python To A Shared Library使用 Cython 将 Python 链接到共享库
【发布时间】:2013-06-04 08:10:36
【问题描述】:

我正在尝试使用Cython 将用C 编写的第三方库与我的python 应用程序集成。我已经为测试编写了所有 python 代码。我无法找到设置此示例的示例。

我有一个手动创建的pyd/pyx 文件。第三方给了我header file (*.h)shared library (*.so)。据我所知,没有其他依赖项。有人可以提供一个如何使用Cythondisutils 进行设置的示例吗?

谢谢

【问题讨论】:

    标签: python c linker cython distutils


    【解决方案1】:

    当然!

    (在下文中,我假设您已经知道如何处理cimport以及.pxd.pyx之间的交互。如果情况不完全如此,请问我将这部分开发为好吧)

    示例(从我的 C++ 项目中获取,但 C 项目的工作方式几乎相同):

    1. Distutils 安装文件:

    假设要创建的扩展名为myext,第三方共享库为libexternlib.so(注意这里的lib*前缀)...

    # setup.py file
    import sys
    import os
    import shutil
    
    from distutils.core import setup
    from distutils.extension import Extension
    from Cython.Distutils import build_ext
    
    # clean previous build
    for root, dirs, files in os.walk(".", topdown=False):
        for name in files:
            if (name.startswith("myext") and not(name.endswith(".pyx") or name.endswith(".pxd"))):
                os.remove(os.path.join(root, name))
        for name in dirs:
            if (name == "build"):
                shutil.rmtree(name)
    
    # build "myext.so" python extension to be added to "PYTHONPATH" afterwards...
    setup(
        cmdclass = {'build_ext': build_ext},
        ext_modules = [
            Extension("myext", 
                      sources=["myext.pyx",
                               "SomeAdditionalCppClass1.cpp",
                               "SomeAdditionalCppClass2.cpp"
                           ],
                      libraries=["externlib"],          # refers to "libexternlib.so"
                      language="c++",                   # remove this if C and not C++
                      extra_compile_args=["-fopenmp", "-O3"],
                      extra_link_args=["-DSOME_DEFINE_OPT", 
                                       "-L./some/extra/dependency/dir/"]
                 )
            ]
    )           
    

    注意:您的外部.so 文件通过libraries 选项链接:

    libraries=["externlib"]   # Without the 'lib' prefix and the '.so' extension...
    

    注意:sources 选项可用于编译一些额外的源文件。

    重要: myext.pxd(不要与.pyd - Windows 的东西混淆)和myext.pyx 应该在同一个目录中。在编译时,首先处理定义文件(如果存在) (more)。

    2。然后运行如下:

    将目录更改为包含您的myext.pxdmyext.pyx 以及上述setup.py 脚本的目录后:

    # setup.sh
    # Make the "myext" Python Module ("myext.so")
    CC="gcc"   \
    CXX="g++"   \
    CFLAGS="-I./some/path/to/includes/ -I../../../DEPENDENCIES/python2.7/inc -I../../../DEPENDENCIES/gsl-1.15"   \
    LDFLAGS="-L./some/path/to/externlib/"   \
        python setup.py build_ext --inplace
    

    地点:

    • libexternlib.so 假定位于 ./some/path/to/externlib/
    • yourheader.h 假定位于 ./some/path/to/includes/

    注意:CFLAGS 也可以使用extra_compile_args 选项进行设置:

    extra_compile_args=["-I./some/path/to/includes/", "-fopenmp", "-O3"]
    

    注意:LDFLAGS 也可以使用extra_link_args 选项进行设置:

    extra_link_args=["-L./some/path/to/externlib/", "-DSOME_DEFINE_OPT", "-L./some/extra/dependency/dir/"]
    

    distutils 构建完成后,您会得到一些新文件,特别是 myext.cppmyext.h,最重要的是 myext.so

    3.之后,您就可以开始了:

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./some/path/to/externlib/
    export PYTHONPATH=$PYTHONPATH:./some/path/to/myext/
    
    # Run some script requiring "myext.so"
    python somescript.py
    

    您新创建的 Python 扩展可以通过其名称导入:

    # somescript.py
    import myext
    from myext import PySomeFeature
    ...
    

    注意关于优化:默认情况下-O2 用于编译扩展,但这可能会被重载(参见上面指定-O3 的设置)。

    注意关于 Cython 路径:如果 Cython 安装在自定义目录中,您可能需要先将其添加到您的环境中:

    PYTHONPATH=$PYTHONPATH:../../../DEPENDENCIES/Cython-0.18 export PYTHONPATH;
    PATH=$PATH:../../../DEPENDENCIES/Cython-0.18/bin; export PATH;
    

    嗯,希望我能讲到要点……

    【讨论】:

    • 您好,感谢您的帮助。我收到以下错误:ld: library not found for -lMYLIB 其中 MYLIB.so 是我要链接的文件 - 有什么想法吗?
    • 算了,我刚刚读到 gcc -l 命令假定您的 *.so 以 lib 开头,所以我删除了它,它发现它并且似乎正在工作。
    • 很高兴听到这个消息。干杯;-)
    • 非常好的代码——除了结尾的反斜杠是什么?你不需要它们(你在括号里)——一般来说,在正确的 Python 中你永远不需要尾随反斜杠(总是用括号、大括号或方括号来做)。
    • @Dilawar 不确定您所说的“运输”是什么意思。发布库后,唯一的要求是将其包含文件夹的路径添加到环境中($LD_LIBRARY_PATH$PYTHONPATH- 请参阅上述答案的第三点)。使用绝对路径并将这些导出命令添加到您的 .profile.bashrc 以使其永久化。
    猜你喜欢
    • 1970-01-01
    • 2013-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-13
    • 1970-01-01
    相关资源
    最近更新 更多