Search code examples
pythonc++swig

Using swig Python wrapper: argument 2 of type 'std::unordered_set< std::string > const &'


I am updating an old project using (parent project of) the Python package coqui_stt_ctcdecoder generated from C++ using SWIG. Some parameter types in some methods have changed. I am stuck with the method Scorer::fill_dictionary that takes const std::unordered_set<std::string>& as an argument in C++. In the old Python code a list of bytes is passed, but that no longer works, as well as a set. I have no idea what type to put there. The error is

Traceback (most recent call last):
  File "/mnt/d/shared/speech/dsalign/STT-align/align/align.py", line 693, in <module>
    main()
  File "/mnt/d/shared/speech/dsalign/STT-align/align/align.py", line 451, in main
    create_bundle(alphabet_path, scorer_path + '.' + 'lm.binary', scorer_path + '.' + 'vocab-500000.txt', scorer_path, False, 0.931289039105002, 1.1834137581510284)
  File "/mnt/d/shared/speech/dsalign/STT-align/align/generate_package.py", line 75, in create_bundle
    scorer.fill_dictionary(words)
  File "/mnt/d/shared/speech/dsalign/STT-align/venv/lib/python3.10/site-packages/coqui_stt_ctcdecoder/swigwrapper.py", line 1269, in fill_dictionary
    return _swigwrapper.Scorer_fill_dictionary(self, vocabulary)
TypeError: in method 'Scorer_fill_dictionary', argument 2 of type 'std::unordered_set< std::string > const &'

EDIT: I have tried a list and a set of str and bytes, all with the above exception. I have used Python 3.8 on Windows and WSL.


Solution

  • SWIG includes support for std::unordered_set, but note that the interface oddly doesn't accept Python set objects. tuple and list work, however.

    Tested example:

    test.i

    %module test
    
    // Code injected into wrapper
    %{
    #include <iostream>
    #include <string>
    #include <unordered_set>
    
    // Function using the parameter type from OP error message
    void func(std::unordered_set<std::string> const &string_set) {
        for(auto& s : string_set)
            std::cout << s << std::endl;
    }
    %}
    
    // SWIG support for templates
    %include <std_unordered_set.i>
    %include <std_string.i>
    // Must instantiate the specific template used
    %template(string_set) std::unordered_set<std::string>;
    
    // Tell SWIG to wrap the function
    void func(std::unordered_set<std::string> const &string_set);
    

    Demo:

    >>> import test
    >>> test.func(['abc','def','abc','ghi'])  # list works
    abc
    def
    ghi
    >>> s = test.string_set(['aaa','bbb','ccc','aaa','bbb'])
    >>> test.func(s)
    aaa
    bbb
    ccc
    >>> s = test.string_set(('aaa','bbb','ccc','aaa','bbb')) # tuple works
    >>> list(s)
    ['aaa', 'bbb', 'ccc']
    >>> test.func({'abc','def'})  # set doesn't work
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "C:\test.py", line 194, in func
        return _test.func(string_set)
    TypeError: in method 'func', argument 1 of type 'std::unordered_set< std::string,std::hash< std::string >,std::equal_to< std::string >,std::allocator< std::string > > const &'