Skip to content

Instantly share code, notes, and snippets.

@rjzak
Last active April 16, 2024 09:00
Show Gist options
  • Star 64 You must be signed in to star a gist
  • Fork 18 You must be signed in to fork a gist
  • Save rjzak/5681680 to your computer and use it in GitHub Desktop.
Save rjzak/5681680 to your computer and use it in GitHub Desktop.
Convert between Python list/tuples and C++ vectors
#include <Python.h> // Must be first
#include <vector>
#include <stdexcept>
#include "PyUtils.h"
using namespace std;
// =====
// LISTS
// =====
PyObject* vectorToList_Float(const vector<float> &data) {
PyObject* listObj = PyList_New( data.size() );
if (!listObj) throw logic_error("Unable to allocate memory for Python list");
for (unsigned int i = 0; i < data.size(); i++) {
PyObject *num = PyFloat_FromDouble( (double) data[i]);
if (!num) {
Py_DECREF(listObj);
throw logic_error("Unable to allocate memory for Python list");
}
PyList_SET_ITEM(listObj, i, num);
}
return listObj;
}
// ======
// TUPLES
// ======
PyObject* vectorToTuple_Float(const vector<float> &data) {
PyObject* tuple = PyTuple_New( data.size() );
if (!tuple) throw logic_error("Unable to allocate memory for Python tuple");
for (unsigned int i = 0; i < data.size(); i++) {
PyObject *num = PyFloat_FromDouble( (double) data[i]);
if (!num) {
Py_DECREF(tuple);
throw logic_error("Unable to allocate memory for Python tuple");
}
PyTuple_SET_ITEM(tuple, i, num);
}
return tuple;
}
PyObject* vectorVectorToTuple_Float(const vector< vector< float > > &data) {
PyObject* tuple = PyTuple_New( data.size() );
if (!tuple) throw logic_error("Unable to allocate memory for Python tuple");
for (unsigned int i = 0; i < data.size(); i++) {
PyObject* subTuple = NULL;
try {
subTuple = vectorToTuple_Float(data[i]);
} catch (logic_error &e) {
throw e;
}
if (!subTuple) {
Py_DECREF(tuple);
throw logic_error("Unable to allocate memory for Python tuple of tuples");
}
PyTuple_SET_ITEM(tuple, i, subTuple);
}
return tuple;
}
// PyObject -> Vector
vector<float> listTupleToVector_Float(PyObject* incoming) {
vector<float> data;
if (PyTuple_Check(incoming)) {
for(Py_ssize_t i = 0; i < PyTuple_Size(incoming); i++) {
PyObject *value = PyTuple_GetItem(incoming, i);
data.push_back( PyFloat_AsDouble(value) );
}
} else {
if (PyList_Check(incoming)) {
for(Py_ssize_t i = 0; i < PyList_Size(incoming); i++) {
PyObject *value = PyList_GetItem(incoming, i);
data.push_back( PyFloat_AsDouble(value) );
}
} else {
throw logic_error("Passed PyObject pointer was not a list or tuple!");
}
}
return data;
}
// PyObject -> Vector
vector<int> listTupleToVector_Int(PyObject* incoming) {
vector<int> data;
if (PyTuple_Check(incoming)) {
for(Py_ssize_t i = 0; i < PyTuple_Size(incoming); i++) {
PyObject *value = PyTuple_GetItem(incoming, i);
data.push_back( PyFloat_AsDouble(value) );
}
} else {
if (PyList_Check(incoming)) {
for(Py_ssize_t i = 0; i < PyList_Size(incoming); i++) {
PyObject *value = PyList_GetItem(incoming, i);
data.push_back( PyFloat_AsDouble(value) );
}
} else {
throw logic_error("Passed PyObject pointer was not a list or tuple!");
}
}
return data;
}
#ifndef PYUTILS_H__
#define PYUTILS_H__
#include <Python.h>
#include <vector>
using namespace std;
PyObject* vectorToList_Float(const vector<float> &data);
PyObject* vectorToTuple_Float(const vector<float> &data);
PyObject* vectorVectorToTuple_Float(const vector< vector< float > > &data);
vector<float> listTupleToVector_Float(PyObject* incoming);
vector<int> listTupleToVector_Int(PyObject* incoming);
#endif
@scm-ns
Copy link

scm-ns commented Dec 18, 2016

Thanks a lot ! I couldn't figure out how to do the conversion from list to std::vector !

@mrgloom
Copy link

mrgloom commented Feb 15, 2019

I wonder why for listTupleToVector_Int we use PyFloat_AsDouble (and then it's converted to int)?

@KevinAS28
Copy link

Thanks a lot !!!

@MrRutabaga
Copy link

Thank you very much ! I modified your code to convert a list to vector<vector>, helped a lot.

@leonardotoledo
Copy link

Thank you!!

@Deepak2405
Copy link

Hi, where can I find PyUtils.h.

Thank you.

@rjzak
Copy link
Author

rjzak commented Apr 12, 2021

Added!

@demorise
Copy link

Thanks! This was really helpful.

@CYTangCY
Copy link

Thanks!

@nishitnshah
Copy link

Is there an efficient way to implement vector<int> listTupleToVector_Int(PyObject* incoming) without walking through the list?

@rjzak
Copy link
Author

rjzak commented Nov 13, 2023

I don't think so since the Python API only exposes the elements one at a time with PyList_GetItem() and the internal representation doesn't make it easy to access the data directly https://github.com/python/cpython/blob/main/Include/object.h

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment