简体   繁体   English

使用Cython将Python链接到共享库

[英]Using Cython To Link Python To A Shared Library

I am trying to integrate a third party library written in C with my python application using Cython . 我正在尝试使用CythonC编写的第三方库与我的python应用程序Cython I have all of the python code written for a test. 我已经为测试编写了所有的python代码。 I am having trouble finding an example for setting this up. 我很难找到设置此示例的方法。

I have a pyd/pyx file I created manually. 我有一个手动创建的pyd/pyx文件。 The third party has given me a header file (*.h) and a shared library (*.so) . 第三方给了我一个header file (*.h)和一个shared library (*.so) As far as I can tell, there are no other dependencies. 据我所知,没有其他依赖项。 Can someone provide an example of how to set this up using Cython and disutils ? 有人可以提供使用Cythondisutils进行设置的示例吗?

Thanks 谢谢

Sure ! 当然可以!

(In the following, I assume that you already know how to deal with cimport and the interactions between .pxd and .pyx . If this is not completely the case, just ask and I will develop that part as well) (在下面,我假设您已经知道如何处理cimport以及.pxd.pyx之间的交互。如果不是完全如此,请问一下,我也将开发该部分)

The sample (grabbed from a C++ project of mine, but a C project would work pretty much the same) : 示例(来自我的C ++项目,但C项目的工作原理几乎相同):

1. The Distutils setup file : 1. Distutils安装文件:

Assuming that the extension to be created will be called myext and the 3rd party shared library is libexternlib.so (note the lib* prefix, here)... 假设要创建的扩展名为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 : Your external .so file is linked via the libraries option : 注意:您的外部.so文件通过“ libraries选项链接:

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

Note : the sources option can be used to get some additional source files compiled. 注意: sources选项可用于获取一些其他源文件。

Important : myext.pxd (do not confound with .pyd - Windows stuff) and myext.pyx should be in the same directory. 重要提示: myext.pxd (不要与.pyd混淆-Windows东西)和myext.pyx应该位于同一目录中。 At compile time the definition file, if it exists, is processed first ( more ). 在编译时,将首先处理定义文件(如果存在)( 更多内容 )。

2. Then run it as follows : 2.然后按以下方式运行:

After having changed directory to the one containing your myext.pxd , your myext.pyx , as well as the above setup.py script : 将目录更改为包含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

Where : 哪里:

  • libexternlib.so is assumed to be located at ./some/path/to/externlib/ libexternlib.so被假定为位于./some/path/to/externlib/
  • yourheader.h is assumed to be located at ./some/path/to/includes/ yourheader.h假定位于./some/path/to/includes/

Note : CFLAGS could also have been setup using the extra_compile_args option : 注意: CFLAGS也可以使用extra_compile_args选项设置:

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

Note : LDFLAGS could also have been setup using the extra_link_args option : 注意:还可以使用extra_link_args选项设置LDFLAGS

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

Once distutils is done with the build, you get some new files, specially the myext.cpp , myext.h and most importantly, the myext.so . distutils完成构建后,您将获得一些新文件,尤其是myext.cppmyext.h ,最重要的是myext.so

3. After that, you're good to go : 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

Where your freshly created Python extension can be imported by its name : 新创建的Python扩展名可以通过其名称导入:

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

Note about Optimization : By default -O2 is used for compiling the extension, but this can be overloaded (see above setup where -O3 is specified). 关于优化的注意事项 :缺省情况下, -O2用于编译扩展名,但是可以重载(请参见上面的设置,其中指定了-O3 )。

Note about Cython paths : If Cython was installed in a custom directory, you might want to add it to your environment, before all : 关于Cython路径的注意事项 :如果将Cython安装在自定义目录中,则可能需要先将其添加到您的环境中:

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

Well, hope I covered the main points... 好吧,希望我能讲到要点...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM