Question

How to make unordered_map from c struct to int in cython?

I try to run the following code: Main.py

# !/usr/bin/env python
# encoding: utf-8
import pyximport


pyximport.install()
from foo import Fun

Fun()

Foo.pyx

# cython: experimental_cpp_class_def=True
#!/usr/bin/env python
# encoding: utf-8
from libcpp.unordered_map cimport unordered_map
from libcpp.map cimport map
from libcpp.string cimport string

cdef cppclass mystruct:
    int i,j

    bint equal_to "operator=="(const mystruct t) const:
         return this.i == t.i and this.j == t.j

    bint myhash "hash"(const mystruct t) const:
         return hash(i)+hash(i) # how to calculate it properly?


def Fun():
    cdef:
        unordered_map[mystruct,int] dDict
        mystruct A

    A.i=111

    dDict[A]=1234
    print A.i
    print dDict[A]

foo.pyxbld

def make_ext(modname, pyxfilename):
    from distutils.extension import Extension
    return Extension(name=modname,
                     sources=[pyxfilename],
                     experimental_cpp_class_def=True,
                     language='C++')

I get the following error:

        C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE\functional(109) : while compiling class template member function 'bool std::equal_to<_Ty>::operator ()(const _Ty &,const _Ty &) const'
        with
        [
            _Ty=__pyx_t_3foo_mystruct
        ]
        C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE\xhash(184) : see reference to class template instantiation 'std::equal_to<_Ty>' being compiled
        with
        [
            _Ty=__pyx_t_3foo_mystruct
        ]
        C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE\unordered_map(74) : see reference to class template instantiation 'stdext::_Hash_compare<_Kty,_Hasher,_Keyeq>' being compiled
        with
        [
            _Kty=__pyx_t_3foo_mystruct,
            _Hasher=std::tr1::hash<__pyx_t_3foo_mystruct>,
            _Keyeq=std::equal_to<__pyx_t_3foo_mystruct>
        ]
        C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE\xhash(191) : see reference to class template instantiation 'std::tr1::_Umap_traits<_Kty,_Ty,_Tr,_Alloc,_Mfl>' being compiled
        with
        [
            _Kty=__pyx_t_3foo_mystruct,
            _Ty=int,
            _Tr=stdext::_Hash_compare<__pyx_t_3foo_mystruct,std::tr1::hash<__pyx_t_3foo_mystruct>,std::equal_to<__pyx_t_3foo_mystruct>>,
            _Alloc=std::allocator<std::pair<const __pyx_t_3foo_mystruct,int>>,
            _Mfl=false
        ]
        C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE\unordered_map(86) : see reference to class template instantiation 'stdext::_Hash<_Traits>' being compiled
        with
        [
            _Traits=std::tr1::_Umap_traits<__pyx_t_3foo_mystruct,int,stdext::_Hash_compare<__pyx_t_3foo_mystruct,std::tr1::hash<__pyx_t_3foo_mystruct>,std::equal_to<__pyx_t_3foo_mystruct>>,std::allocator<std::pair<const __pyx_t_3foo_mystruct,int>>,false>
        ]
        C:\Users\LENOVO\.pyxbld\temp.win-amd64-2.7\Release\pyrex\foo.cpp(796) : see reference to class template instantiation 'std::tr1::unordered_map<_Kty,_Ty>' being compiled
        with
        [
            _Kty=__pyx_t_3foo_mystruct,
            _Ty=int
        ]
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE\functional(1265) : error C2440: 'type cast' : cannot convert from 'const __pyx_t_3foo_mystruct' to 'size_t'
        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
        C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE\functional(1264) : while compiling class template member function 'size_t std::tr1::hash<_Kty>::operator ()(const _Kty &) const'
        with
        [
            _Kty=__pyx_t_3foo_mystruct
        ]
        C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\INCLUDE\xhash(183) : see reference to class template instantiation 'std::tr1::hash<_Kty>' being compiled
        with
        [
            _Kty=__pyx_t_3foo_mystruct
        ]

How should I properly define hash function and correct the program to make it work? Thanks in advance for your help.

Was it helpful?

Solution

The problem is not to calculate properly the hash value; The problem is to tell the std C++ lib to use the one which you defined. For this you either

  • have to overload std::hash<mystruct> but this cannot be done from Cython as far as I know

  • or to pass the extra template parameter which forces you to re-wrap all the unordered_map stuff since Cython only wrap the two parameter default version. And this is not counting the fact that you will have to hack to pass a non type template parameter from Cython since this is not yet supported.

So my short answer would be : write a real C++ wrapper file.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top