0

Long time reader, first one I didn't find an answer to...

I'm writing a c++(11) class in a mainly C project which is swig-wrapped to Python. I can not expose c++ types to Python, only c-types. I need to save some c++ stl containers during c++ -> python -> c++ which is possible with opaque structs.

However when filling the struct* imp I encounter a segfault for std::list and std::vector, whereas std::unordered_map is fine. MWE:

#include <stdio.h>

//Include c++ stuff here
#include <iostream>
#include <unordered_map>
#include <list>
#include <queue>
#include <utility>
#include <algorithm>

//https://stackoverflow.com/a/27216842/9152353
template <typename T>
struct hash_vector {
    T operator()(const std::vector<T> &V) const {
        T hash = V.size();
        for(auto &i : V) {
            hash ^= i + 0x9e3779b9 + (hash << 6) + (hash >> 2);
        }
        return hash;
    }
};
typedef std::vector<size_t> vec;

typedef std::unordered_map<const vec, vec, hash_vector<size_t>> _map;
typedef std::list<std::pair<std::list<vec>, std::list<size_t>>> complexList_t;
typedef std::list<size_t> listSize_t;

struct IntermediateResults {
  _map theMap;
  complexList_t cmplxList;
  listSize_t simpleList;
  vec vector;  
};

int main()
{
    // Some dummy values 
    _map theMap;
    vec _key(4, 1);
    _key[2] = 2;
    vec _value(10,3);
    _value[1] = 4;
    theMap.emplace(_key, _value);
    auto it = theMap.find(_key);
    printf("Map: %lu %lu\n", it->second[0], it->second[1]);

    complexList_t cmplxList;
    std::list<vec> bins;
    bins.push_back(_key);
    std::list<size_t> cands;
    cands.push_back(5);
    auto _pair = std::make_pair(bins, cands);
    cmplxList.push_back(_pair);
    
    std::list<size_t> cand2;
    cand2.push_back(6);
    
    // This is okay
    IntermediateResults im;
    im.theMap = theMap;
    im.cmplxList = cmplxList;
    printf("imAf %lu %lu\n", im.theMap.size(), im.cmplxList.size());
    it = im.theMap.find(_key);
    printf("imMap: %lu %lu\n", it->second[0], it->second[1]);
    
    // This however is not okay
    IntermediateResults* imp = NULL;
    imp = (IntermediateResults*) calloc(1, sizeof(*imp));
    imp->theMap = theMap;
    it = imp->theMap.find(_key);
    printf("impMap: %lu %lu\n", it->second[0], it->second[1]);
    imp->vector = _key;
    printf("Still alive\n");

    imp->simpleList = cand2;     //This leads to segfault
    imp->cmplxList = cmplxList;  //This leads to segfault

    printf("Dead\n");
    return 0;
}

Output:

Map: 3 4
imAf 1 1
imMap: 3 4
impMap: 3 4
Map: 3 4
imAf 1 1
imMap: 3 4
impMap: 3 4
Still alive

The dummy output for the map looks okay. When I do the whole c++->python->c++ thing with only the map, it works beautifully. But when I use a 'simpler' type like vector/list it segfaults on assignment.

I really don't get it, what is the proper way to do it?

Maahk
  • 11
  • 3

0 Answers0