代码之家  ›  专栏  ›  技术社区  ›  Eric

通过c调用包含多个pyx文件的cython库++

  •  2
  • Eric  · 技术社区  · 6 年前

    *.so 每一个python源码,这是非常不方便的。

    这是你的名字 setup.py 文件:

    from distutils.core import setup
    from distutils.extension import Extension
    from Cython.Build import cythonize
    
    sourcefiles = ['project_interface.pyx', 'impl_file1.pyx']
    
    setup(
        ext_modules = cythonize(sourcefiles)
    )
    

    项目接口.pyx:

    # distutils: language = c++
    
    import impl_file1
    
    cdef public void HelloWorld():
        print "Calling Hello World"
        impl_file1.helloworld_func()
    

    impl\ U文件1.pyx:

    def helloworld_func():
        print 'Hello World'
    

    我尝试修改setup.py,将所有python代码捆绑到一个库中,如下所示:

    setup(
          ext_modules = cythonize([Extension("my_project", sourcefiles, language='c++')])
    )
    

    不幸的是,在执行 void HelloWorld() ,应用程序无法再提交impl\u file1。我得到:

    Calling Hello World
    NameError: name 'impl_file1' is not defined
    Exception NameError: "name 'impl_file1' is not defined" in 'project_interface.HelloWorld' ignored
    

    驱动它的c++程序是:

    #include <Python.h>
    #include "project_interface.h"
    
    int main(int argc, const char** argv){
        Py_Initialize();
        initproject_interface();
        HelloWorld();
        Py_Finalize();
    
    
        return 0;
    }
    

    此应用程序在使用多个 *所以呢

    在这两种情况下,编译都非常简单:

    python setup.py build_ext --inplace
    mv my_project.so libmy_project.so
    g++ main.cpp -o main `python2-config --cflags --ldflags` -L. -lmy_project
    

    有没有办法让单一共享库解决方案发挥作用?

    2 回复  |  直到 5 年前
        1
  •  2
  •   DavidW    6 年前

    关于将多个Cython模块捆绑在一起(例如。 1 , 2

    您需要使用C API函数 PyImport_AppendInittab 给蟒蛇治疗 impl_file1 作为内置模块,因此它不会搜索要导入的文件的路径。首先提供导入函数的声明(因为您无法从头文件中获得该声明):

    extern "C" {
    // PyObject* PyInit_impl_file1(); // Python 3
    void initimpl_file1(); // Python 2
    }
    

    main ,之前 Py_Initialize ,添加:

    PyImport_AppendInittab("impl_file1", initimpl_file1); // change the name for Python 3
    
        2
  •  1
  •   ead    6 年前

    对我来说,@DavidW的解决方案需要一些调整(在一个稍微不同的场景中,但我没想到会有不同)。以下是我的设置:

    foo.pyx文件 :

    cdef extern from "Python.h":
        int PyImport_AppendInittab(const char *name, object (*initfunc)())
    
    
    cdef extern from *:
        """
        PyObject *PyInit_bar(void);
        """
        object PyInit_bar()
    
    PyImport_AppendInittab("bar", PyInit_bar)
    
    import bar  # HERE The error happens
    

    条形图.pyx :

    print("bar imported")
    

    :

    from distutils.core import setup
    from distutils.extension import Extension
    from Cython.Build import cythonize
    
    sourcefiles = ['foo.pyx', 'bar.pyx']
    
    
    setup(
        ext_modules = cythonize([Extension("foo", sourcefiles)])
    )
    

    现在在与 python setup.py build_ext -i ,导致错误:

    import foo
    ImportError: 'bar' is not a built-in module
    

    here sys.builtin_module_names :

    ...
    import sys
    sys.builtin_module_names = list(sys.builtin_module_names)+["bar"]
    import bar