2

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.

9
  • see stackoverflow.com/questions/1842941/… it may be appropriate to make a map than to turn things into arrays via loops. or even boost.org/doc/libs/1_41_0/libs/python/doc/index.html Commented Aug 23, 2020 at 16:30
  • Some time ago when I needed to interface some Python code with C++, I found Python's documentation to be well written, organized, and telling me everything I needed to know. Which parts of Python's extensive documentation, on this subject matter, are unclear to you, specifically? Also, it's troubling that you do not have "prior knowledge of C\C++". C++ is the most complicated general purpose programming language in use today. This kind of code, interfacing C++ to another language is hard enough. Attempting to do that without basic understanding of C++ is going to be pretty much a no-go, sorry. Commented Aug 23, 2020 at 16:35
  • @Abel My goal is not use mapping as i cannot declare size with maps, hence i am trying to convert it to arrary of one dimension. Commented Aug 23, 2020 at 16:40
  • @Vivek so you are just looking to stackoverflow.com/questions/16228248/… ? Commented Aug 23, 2020 at 16:46
  • @Abel i wish, but i dont want to perform any kind of transformation to dict in the python function. it has to happen only in the warpper. Commented Aug 23, 2020 at 16:50

1 Answer 1

1

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?
}

Sign up to request clarification or add additional context in comments.

6 Comments

i cant thank you enough for you help. One last doubt, do you know what exactly is happening here " int res = PyArg_ParseTuple(args, "Oi", &e_obj, &d); " ?
It's an alternate method that avoids calls like PyFloat_AsDouble and can be used to strip the PyObject layer for an entire list of variables. In this case, O and i respectively mean: leave first in list as PyObject * (for e), and convert second to int for d. Note that the args is supposed to be a python tuple (list) of all the necessary python variables. docs.python.org/2.0/ext/parseTuple.html
Thanks you so much agin for your help.
is there anythis similar that we can use for tuples and sets.
Something to use instead of "PyDict_Next(srcDict, &iteratorPPOS, NULL, &currentVal)" that can iterate over tuples and sets and get values
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.