2
  • This is my python function:
if __name__ == "__main__":
    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 dict as 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 to accept the dict values from python function and convert it to array values suitable for C in the wrapper. I have no prior knowledge of C\C++ and i am stuck. Any help will be greatly helpful. thanks
  • see https://stackoverflow.com/questions/1842941/translating-python-dictionary-to-c it may be appropriate to make a map than to turn things into arrays via loops. or even https://www.boost.org/doc/libs/1_41_0/libs/python/doc/index.html – Abel Aug 23 '20 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. – Sam Varshavchik Aug 23 '20 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. – Vivek Raven Aug 23 '20 at 16:40
  • @Vivek so you are just looking to https://stackoverflow.com/questions/16228248/how-can-i-get-list-of-values-from-dict ? – Abel Aug 23 '20 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. – Vivek Raven Aug 23 '20 at 16:50
  • For clarification then: 1) you cannot build and use a C++ map with calls from python in place of a python dict; 2) you cannot convert the python dict to another, more generic, data form before passing it to C++. – Abel Aug 23 '20 at 17:00
  • @abel yes that's correct... I cannot use maps or unordered maps in c++ and I can only use arrays. Also I cannot convert dict to arrays directly in python. The conversion has to happen only in wrapper – Vivek Raven Aug 23 '20 at 17:46
  • that means your options are limited to passing the dict into C++ and using the methods in https://docs.python.org/3/c-api/dict.html – Abel Aug 24 '20 at 13:33
  • @abel yes dict will then have limited functionality and thats fine with me.... any help for converting this dict object to arrays will be helpful – Vivek Raven Aug 24 '20 at 14:29

1 Answers1

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

Abel
  • 111
  • 4
  • 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); " ? – Vivek Raven Aug 25 '20 at 13:34
  • 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. https://docs.python.org/2.0/ext/parseTuple.html – Abel Aug 25 '20 at 21:12
  • Thanks you so much agin for your help. – Vivek Raven Aug 26 '20 at 11:44
  • is there anythis similar that we can use for tuples and sets. – Vivek Raven Aug 27 '20 at 15:45
  • Something to use instead of "PyDict_Next(srcDict, &iteratorPPOS, NULL, &currentVal)" that can iterate over tuples and sets and get values – Vivek Raven Aug 27 '20 at 15:46
  • tuples are not as convenient, but are usually computationally more efficient. You will have to use a for loop, PyTuple_Size, and PyTuple_GetItem. If I recall correctly first valid index is 0, and last is 1 less than the size (similar to a std::vector). Lists are also very similar. https://docs.python.org/3/c-api/tuple.html https://docs.python.org/3.3/c-api/list.html – Abel Aug 28 '20 at 07:16