如何使用stl list参数为c ++函数构建cython包装器

时间:2014-01-20 19:09:02

标签: python c++ stl cython

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

#ifndef TESTLIB_H
#define TESTLIB_H

#include <iostream>
#include <list>

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

#endif

(printlist.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。有没有办法使用&#34; extern&#34;来声明这个?如果没有,使用此功能的最简单方法是什么。

这是我的尝试:

(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

1 个答案:

答案 0 :(得分:4)

您的代码存在两个主要问题。

第一个是您在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脚本,用于调用我添加到list_test的{​​{1}}函数。

test.pyx

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