Vivek Raven
Vivek Raven

Reputation: 25

How to send Python dict to C++

This is my Python code:

file = open("data_input.txt", "r")
contents = file.read()
e = ast.literal_eval(contents)
neighbour_num= 4
new_data = 300
result = np.ndarray((4,4), dtype='int32', buffer=np.zeros((4,4), dtype='int32'))
c_module.mmult_wrapper(e, new_data, neighbour_num, result)

This is my C++ function, where I want to use a dictionary as an array:

void mmult(double new_data, double neighbour_num, double e[100], int32_t result[16]) {
   double distances[100];
   unsigned distances_front = 0;
   unsigned distances_back = 0;

   double keys[100];
   unsigned keys_front = 0;
   unsigned keys_back = 0;
 
   for (int i=0; i<(int)100; i=i+1) {
      double temp_distance = (new_data-e[i]);
      double sq_tmp = (temp_distance*temp_distance);
      double sqrt = (sq_tmp/2);
      double temp = 0;
      while (sqrt!=temp) {
         temp = sqrt;
         sqrt = (((sq_tmp/temp)+temp)/2);
      }
      distances[distances_front++] = (sqrt);
      keys[keys_front++] = (e[i-1]);
   }
   for (int i=0; i<(int)(keys_front - keys_back); i=i+1) {
      for(int j=(i+1); j<(int)(distances_front - distances_back); j=j+1) {
         if (distances[i]>distances[j]) {
            distances[i] = distances[j];
            distances[j] = distances[i];
            keys[i] = keys[j];
            keys[j] = keys[i];
         }
      }
   }
   for (int i=0; i<(int)neighbour_num; i=i+1) {
      result[i] = keys[i];
   }
} 

This is the wrapper function I have:

#include <Python.h>
#include <numpy/arrayobject.h>
#include "spyc.h"
#include "caller.h"

static PyObject* mmult_wrapper(PyObject* self, PyObject* args) {

   int32_t e;
   int32_t new_data;
   int32_t neighbour_num;
   int32_t result;

   int res = PyArg_ParseTuple(args, "Oi", &e_obj, &d);

   if (!res)
      return NULL;

   /* call function */
   mmult_caller(e,d);
}

My objective is to accept the dict values from Python and convert it to array values suitable for C++ in the wrapper.

Upvotes: 2

Views: 1265

Answers (1)

Abel
Abel

Reputation: 111

you will likely need to include dictobject.h, floatobject.h, , if not already pulled in via other headers. Here is a way to grab all the values from a dict of floating point numbera to a vector. Depending on what's actually in the dict and how that's structured you may want to look at keys and other pieces. Note that this is C++ and thus should be compiled as such.


//returns true on success
bool dictToVector(PyObject *  srcDict, std::vector<double> & destVector) {
 destVector.clear();
 if(PyDict_Check(srcDict)) {
  Py_ssize_t numItems = PyDict_Size(srcDict);
  destVector.reserve(numItems);
  Py_ssize_t iteratorPPOS = 0;
  PyObject * currentVal;
  while(PyDict_Next(srcDict, &iteratorPPOS, NULL, &currentVal) {
   // might be worth checking PyFloat_Check...
   destVector.push_back(PyFloat_AsDouble(currentVal));
  }
  return (numItems == destVector.size());
 }
 else { // not a dict return with failure
  return false;
 }
}

Your wrapper will be similar at the end in that it will need to copy the result of mmult into the of result type numpy.ndarray.

Usage of the above something like:


PyObject* mmult_wrapper(PyObject * e, PyObject * new_data, PyObject * neighbour_num, PyObject * result) {
 int32_t Cresult[16];
 std::vector<double> Ce;
 bool noErrorSoFar = dictToVector(e,Ce);
 if(Ce.size() == 100) {
  mmult(PyFloat_AsDouble(new_data) , PyFloat_AsDouble( neighbour_num), Ce.data(), Cresult);
 }
else { // not 100 doubles in the data read!
  noErrorSoFar = false;
 }

... //some stuff to copy Cresult to the python, and return something meaningful?
}

Upvotes: 1

Related Questions