dimanche 2 décembre 2018

Cythonize .pyx file with std=c++11 flag

I'm new to Cython and I'm trying to create an C++ extension in Python for a dictionary but am having problems compiling and importing it.

I have the following files: Map.h, Map.cpp, kmap.pyx, and setup.py (all in the same directory) and was more or less trying to follow the Rectangle example here: https://cython.readthedocs.io/en/latest/src/userguide/wrapping_CPlusPlus.html

Map.h:

#include <unordered_map>
#include <string>

namespace dictionary {
class Map {
private:
    std::unordered_map<std::string, short> hashmap;

public:
    Map();
    void add(std::string kmer, short abundance);
    short get(std::string kmer);
    };
}

Map.cpp:

#include "Map.h"

namespace dictionary {

    Map::Map() {}

    void Map::add(std::string kmer, short abundance) {
        hashmap[kmer] = (abundance > 255) ?  255 : abundance;
    }

    short Map::get(std::string kmer) {
        return hashmap[kmer];      
    }
}

kmap.pyx:

from Map cimport Map

cdef class KMap:
    cdef Map c_map

def __cinit__(self):
    self.c_map = Map()

def add(self, kmer, abundance):
    self.c_map.add(kmer, abundance)

def get(self, kmer):
    return self.c_map.get(kmer)

setup.py:

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

setup(ext_modules=cythonize("kmap.pyx"))

However, when I run python setup.py build_ext --inplace I get the following error: Map.h:1:25: fatal error: unordered_map: No such file or directory #include

It appears that this was because unordered map is a C++11 feature, so I tried changing my setup.py file to compile with std=c++11:

ext_module = Extension(
name="Map",
sources=["Map.cpp"],
language="c++",
extra_compile_args=["-std=c++11"],
extra_link_args=["-std=c++11"])

setup(name="kmap", ext_modules=[ext_module])

But when I start a Python session and try to import Map or kmap, then I get the following error: ImportError: dynamic module does not define module export function (PyInit_Map)

I'm generally confused about how to cythonize the .pyx file and compile the .cpp code with the -std=c++11 flags so that I can import the extension.

I'm calling setup.py with python3 and starting a python3 session so I don't think it's a difference in python versions. I tried adding the .pyx file as a source but then I get an "unknown file type '.pyx' error. I tried to creating separate extensions in the setup.py file for the the .cpp file and the .pyx file and all the things listed here: Cython compiled C extension: ImportError: dynamic module does not define init function. Nothing I've done so far has worked. I have gcc version 4.8.5 and cython version .29. Any help is greatly appreciated!

Aucun commentaire:

Enregistrer un commentaire