【问题标题】:How to build a cython wrapper for c++ function with stl list parameter如何使用 stl list 参数为 c++ 函数构建 cython 包装器
【发布时间】:2014-01-20 19:09:01
【问题描述】:

考虑以下简单的 C++ 代码。 (printlist.h)

#ifndef TESTLIB_H
#define TESTLIB_H

#include <iostream>
#include <list>

void printlist(std::list<int> &);

#endif

(打印列表.c)

#include "printlist.h"

using namespace std;

void printlist(list<int> &l)
  {
  for(list<int>::const_iterator i = l.begin(); i != l.end(); i++)
  cout << *i << ' ';
  cout << endl;
  }

我的问题是如何将此代码与 cython 一起使用,困难在于 printlist 需要一个 stl::list。有没有办法使用“extern”声明它?如果没有,使用此功能的最简单方法是什么。

这是我的尝试:

(test.pyx)

 from libcpp.list cimport list

 cdef extern from "printlist.h":
         void printlist(std::list<int> &)

 cdef list[int] l = range(10)
 printlist(l)

(setup.py)

 from distutils.core import setup
 from distutils.extension import Extension
 from Cython.Distutils import build_ext

 ext_modules = [Extension("test", ["test.pyx", "printlist.C"], language='c++',)]

 setup(cmdclass = {'build_ext': build_ext}, ext_modules = ext_modules)

我得到的错误信息如下:

Error compiling Cython file:
------------------------------------------------------------
...
from libcpp.list cimport list

cdef extern from "printlist.h":
        void printlist(std::list<int> &)
                          ^
------------------------------------------------------------

test.pyx:4:27: Expected an identifier or literal

【问题讨论】:

    标签: python c++ stl cython


    【解决方案1】:

    您的代码有两个主要问题。

    第一个是您在 C 文件中使用 C++。 首先将printlist.c 重命名为printlist.cpp

    第二个是,当您为外部函数定义调用签名时,您使用 C++ 语法进行函数声明,而不是像 http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#templates 中描述的那样对类模板使用大括号。 这就是导致您看到的错误的原因。 线

    void printlist(std::list<int> &)
    

    应该替换为

    void printlist(list[int] &)
    

    您稍后在 Cython 文件中声明新列表时似乎已正确执行此操作。

    另一件值得注意的事情是 Cython 文件在编译时不会执行。 将测试用例包装在可从 Python 调用的函数中可能会更容易。 这是一个工作示例。

    printlist.h(这个和你的一样)

    #ifndef TESTLIB_H
    #define TESTLIB_H
    
    #include <iostream>
    #include <list>
    
    void printlist(std::list<int> &);
    
    #endif
    

    printlist.cpp(我只改了文件扩展名和间距)

    #include "printlist.h"
    
    using namespace std;
    
    void printlist(list<int> &l){
        for(list<int>::const_iterator i = l.begin(); i != l.end(); i++)
        cout << *i << ' ';
        cout << endl;}
    

    test.pyx 请注意,Cython 可以自动从 Python 列表转换为 C++ 列表。 我在输入list_test 函数的参数时这样做。 它还支持http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#standard-library中提到的一些其他类型的自动转换

    from libcpp.list cimport list
    
    cdef extern from "printlist.h":
        void printlist(list[int] &)
    
    def list_test(list[int] l):
        printlist(l)
    

    setup.py(我这里也改了文件扩展名)

    from distutils.core import setup
    from distutils.extension import Extension
    from Cython.Distutils import build_ext
    
    ext_modules = [Extension("test", ["test.pyx", "printlist.cpp"], language='c++',)]
    
    setup(cmdclass = {'build_ext': build_ext}, ext_modules = ext_modules)
    

    test.py 这是一个 Python 脚本,用于调用我添加到 test.pyxlist_test 函数。

    from test import list_test
    
    list_test([1, 2, 3])
    

    运行时,它应该打印字符串“1 2 3”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-31
      • 2015-06-17
      • 1970-01-01
      • 2014-06-05
      • 1970-01-01
      • 1970-01-01
      • 2015-05-13
      • 1970-01-01
      相关资源
      最近更新 更多