1

I want to return a hashmap from C++ to Python using Swig. I am able to print the keys but not able to fetch values. It is giving me this output:

{0: <Swig Object of type 'std::vector< int,std::allocator< int > > *' at 0x7fa646cdfcf0>,
 1: <Swig Object of type 'std::vector<int,std::allocator< int > > *' at 0x7fa646371150>}
<Swig Object of type 'std::vector< int,std::allocator< int > > *' at 0x7fa646cdfcf0>

How to get values in place of swig object. I was able to do with map <int, int> but not able to do with map<int, vector<int> >. I found a github issue which is most closest to it but this doesn't help as I am not able to understand how to use in my code. Sorry I am beginner please help.

myknn.cpp

// Example program
#include <cstdlib>
#include <algorithm>
#include <numeric>
#include <vector>
#include <stdio.h>
#include <iostream>
#include <chrono>
#include <random>
#include <map>
#include <cmath>
#include <map>
#include <math.h>

std::vector<int> argsort(double* input_list, int length) {

    std::vector<int> out(length);
    iota(out.begin(), out.end(), 0);
    sort(out.begin(), out.end(),
       [&input_list](int i1, int i2) {return input_list[i1] < input_list[i2];});
    return out;
}

double edist(double* arr1, double* arr2, int n) {
    double sum = 0.0;
    for (int i=0; i<n; i++) {
        sum += pow(arr1[i] - arr2[i], 2);
    }
    return sqrt(sum); 
}

std::map<int, std::vector<int> > distance_knn(const double *array,int N, int M) {
     std::map<int, std::vector<int> > dist;
    double **arr = new double*[N];
    for (int i = 0; i < N; i++) {
        arr[i] = new double[M];
        for(int j=0; j < M; j++) {
            arr[i][j] = array[i*M+j];
        }
    }

     for (int i=0; i<N; i++) {
        double distances[N];
        for(int j=0; j<N; j++) {
            // distances.push_back();
            distances[j] = edist(arr[i], arr[j], N);
        }
        dist[i] = argsort(distances, N);
    }

    return dist;
}

myknn.i

%module myknn

%{
  #define SWIG_FILE_WITH_INIT  /* To import_array() below */
  #include "myknn.h"
%}

%include "numpy.i"

/* Required for the NumPy C API. Calls to PyArray_SimpleNew
   will result in a segfault if this is omitted */

%include "std_map.i"
%import "std_vector.i" 
namespace std {
// %template (IntVector) std::vector<int>
 %template (mapiv) std::map<int,vector<int> >;
// %template (IntVector) std::vector<int>;
// %template (MapType) std::map<int, IntVector>;
}

%init %{
import_array();
%}

%apply (double* IN_ARRAY2, int DIM1, int DIM2) {
  (const double* array, int m, int n)
}

%include "myknn.h"

myknn.h

/* File knn.h */

#ifndef KNN_H
#define KNN_H
#include <stdio.h>
#include <vector>
#include <map>

/* Define function prototype */
std::map<int,std::vector<int> > distance_knn(const double* array,int m, int n);
std::vector<int> argsort(double* input_list, int length);
double edist(double* arr1, double* arr2, int n);


#endif

build.sh

g++ -fPIC -c myknn.cpp

# Invoke SWIG on the interface file 'knn.i' to produce C/C++ wrapper
# code ('knn_wrap.cpp'):

swig -python -c++ -o myknn_wrap.cpp myknn.i

# Next, compile the wrapper code:

g++ -fPIC -c $(pkg-config --cflags --libs python3) -I /home/kriti/anaconda3/lib/python3.7/site-packages/numpy/core/include  myknn_wrap.cpp

# Link both object files into a shared library '_myknn.so'.
# Python will search for it under this name:

g++ -shared myknn.o myknn_wrap.o -o _myknn.so -lm

main.py

import numpy as np
from myknn import distance_knn

a = np.array([[1,2,3,4], [4,5,6,7]], np.float32)

arr = distance_knn(a)
print(dict(arr))
print(arr[0])

To run:

bash build.sh

python main.py

Specification:

Python 3.7.3

SWIG Version 3.0.12

Compiled with g++ [x86_64-pc-linux-gnu]

Configured options: +pcre

ninjakx
  • 35
  • 13
  • Can't confirm this right now, but from a quick read your `%template` line looks wrong - you're inside the `namespace std {` block, but you also say `std::map` - you don't want to say `std` in both place because you're effectively telling SWIG to wrap `std::std::map` which isn't right. You'll also need to uncomment the `%template` for the vector too. – Flexo Jul 19 '19 at 16:05

0 Answers0