使用 Cython 将 Python 链接到共享库

2024-02-08

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

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

Thanks


Sure !

(在下文中,我假设您已经知道如何处理cimport以及之间的相互作用.pxd and .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/"]
             )
        ]
)           

Note :你的外在.so文件通过以下方式链接libraries选项 :

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

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

重要的 : myext.pxd(不要与.pyd- Windows 的东西)和myext.pyx应该在同一目录中。在编译时,首先处理定义文件(如果存在)(more http://docs.cython.org/src/userguide/sharing_declarations.html).

2.然后运行如下:

将目录更改为包含您的目录后myext.pxd, your myext.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

Where :

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

Note : CFLAGS也可以使用设置extra_compile_args选项 :

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

Note : LDFLAGS也可以使用设置extra_link_args选项 :

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

一旦 distutils 完成构建,您将获得一些新文件,特别是myext.cpp, myext.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
...

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

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

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

好吧,希望我涵盖了要点......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Cython 将 Python 链接到共享库 的相关文章

随机推荐