Consider the following simple c++ code. (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;
}
My question is how to use this code with cython, the difficulty being the fact that printlist takes a stl::list. Is there a way to declare this using "extern"? If not, what is the simplest way to use this function.
(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)
The error message I get is the following:
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
There are two primary issues with your code.
The first one is that you are using C++ in a C file.
Start by renaming printlist.c
to printlist.cpp
The second is that when you define the calling signature for the external function you use the C++ syntax for the function declaration instead of using braces for class templates as is described at http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#templates . This is what is causing the error you are seeing. The line
void printlist(std::list<int> &)
should be replaced by
void printlist(list[int] &)
You seem to have done this correctly later in the Cython file when declaring a new list.
Another thing that is worth noting is that Cython files are not executed upon compilation. It might be easier to wrap your test case in a function that is callable from Python. Here is a working example.
printlist.h
(This is the same as yours)
#ifndef TESTLIB_H
#define TESTLIB_H
#include <iostream>
#include <list>
void printlist(std::list<int> &);
#endif
printlist.cpp
(I only changed the file extension and the spacing)
#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
Notice that Cython can convert automatically from a Python list to a C++ list.
I'm doing this in the typing of the arguments for the list_test
function.
It also supports some other types of automated conversions as is mentioned at 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
(I changed the file extension here as well)
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
This is a Python script to call the list_test
function I added to test.pyx
.
from test import list_test
list_test([1, 2, 3])
When run, it should print the string "1 2 3".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With