0

With boost python tuple, how to loop over tuple items ?

>> more dummy.cpp 
#include <iostream>

#include <boost/python.hpp>

void doStuffs(boost::python::tuple & t) {
  std::cout << "tuple " << std::endl;
  //for (auto i : t) std::cout << i << std::endl; // How to loop over tuple items : does NOT compile ?
}

BOOST_PYTHON_MODULE(dummy) {
  Py_Initialize();    
  def("doStuffs", doStuffs);
}

>> make
g++ -I/usr/include/python2.7 -o dummy.so -shared -fPIC dummy.cpp -lboost_python -lpython2.7

I get :

>> python
Python 2.7.17 (default, Oct 19 2019, 23:36:22) 
[GCC 9.2.1 20191008] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import dummy
>>> dummy.doStuffs((1, 2., 'a'))
tuple 

Where I need to get:

>> python
Python 2.7.17 (default, Oct 19 2019, 23:36:22) 
[GCC 9.2.1 20191008] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import dummy
>>> dummy.doStuffs((1, 2., 'a'))
tuple 
1
2.
a

In c++, how to loop over tuple items and print them ?

UPDATE

Surprisingly, this compiles:

>> more dummy.cpp 
#include <iostream>

#include <boost/python.hpp>

void doStuffs(boost::python::tuple & t) {
  std::cout << "tuple " << std::endl;
  auto t0 = t[0];
  //std::cout << t0 << std::endl;
  //for (auto i : t) std::cout << i << std::endl; // How to loop over tuple items : does NOT compile ?
}

BOOST_PYTHON_MODULE(dummy) {
  Py_Initialize();

  def("doStuffs", doStuffs);
}

>> make
g++ -I/usr/include/python2.7 -o dummy.so -shared -fPIC dummy.cpp -lboost_python -lpython2.7

But this does not:

>> more dummy.cpp 
#include <iostream>

#include <boost/python.hpp>

void doStuffs(boost::python::tuple & t) {
  std::cout << "tuple " << std::endl;
  auto t0 = t[0];
  std::cout << t0 << std::endl;
  //for (auto i : t) std::cout << i << std::endl; // How to loop over tuple items : does NOT compile ?
}

BOOST_PYTHON_MODULE(dummy) {
  Py_Initialize();

  def("doStuffs", doStuffs);
}

>> make
g++ -I/usr/include/python2.7 -o dummy.so -shared -fPIC dummy.cpp -lboost_python -lpython2.7
dummy.cpp: In function ‘void doStuffs(boost::python::tuple&)’:
dummy.cpp:8:16: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
    8 |   std::cout << t0 << std::endl;
In file included from /usr/include/boost/python/proxy.hpp:9,
                 from /usr/include/boost/python/object_attributes.hpp:10,
                 from /usr/include/boost/python/object.hpp:10,
                 from /usr/include/boost/python/class.hpp:15,
                 from /usr/include/boost/python.hpp:18,
                 from dummy.cpp:3:
/usr/include/boost/python/object_operators.hpp:105:1: note: candidate 1: ‘typename boost::python::api::enable_binary<L, R, boost::python::api::object>::type boost::python::api::operator<<(const L&, const R&) [with L = std::basic_ostream<char>; R = boost::python::api::proxy<boost::python::api::item_policies>; typename boost::python::api::enable_binary<L, R, boost::python::api::object>::type = boost::python::api::object]’
  105 | BOOST_PYTHON_BINARY_OPERATOR(<<)
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/iostream:39,
                 from dummy.cpp:1:
/usr/include/c++/9/ostream:174:7: note: candidate 2: ‘std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]’
  174 |       operator<<(bool __n)
      |       ^~~~~~~~
dummy.cpp:8:19: error: no match for ‘operator<<’ (operand types are ‘boost::iterators::enabled<true>::base<boost::python::api::object>::type’ {aka ‘boost::python::api::object’} and ‘<unresolved overloaded function type>’)
    8 |   std::cout << t0 << std::endl;
      |   ~~~~~~~~~~~~~~~~^~~~~~~~~~~~

So the problem lies with the << operator ? Missing cast operator on boost::python::tuple ? Seems no operator defined here https://www.boost.org/doc/libs/1_38_0/libs/python/doc/v2/tuple.html

fghoussen
  • 393
  • 3
  • 16
  • probably because it's a template? this question may help: https://stackoverflow.com/questions/1198260/how-can-you-iterate-over-the-elements-of-an-stdtuple – Jean-François Fabre Jan 27 '20 at 21:29
  • To me, looks like std::tuple is a template, but, boost::python::tuple is a regular class : https://www.boost.org/doc/libs/1_38_0/libs/python/doc/v2/tuple.html. Not sure how boost.fusion could help in this case... – fghoussen Jan 28 '20 at 19:21
  • "does not compile" ? please [edit] to show the actual error message – Jean-François Fabre Jan 28 '20 at 19:43

1 Answers1

0

Solution :

Code must use len and extract :

>> more dummy.cpp 
#include <iostream>

#include <boost/python.hpp>

void doStuffs(boost::python::tuple & t) {
  std::cout << "tuple " << std::endl;
  for (size_t i = 0; i < len(t); i++) {
    std::string s = boost::python::extract<std::string>(boost::python::str(t[i]));
    std::cout << s << std::endl;
  }
}

BOOST_PYTHON_MODULE(dummy) {
  def("doStuffs", doStuffs);
}

Compiling :

>> make
g++ -I/usr/include/python2.7 -o dummy.so -shared -fPIC dummy.cpp -lboost_python

Now back in python:

>> python
Python 2.7.17 (default, Oct 19 2019, 23:36:22) 
[GCC 9.2.1 20191008] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import dummy
>>> dummy.doStuffs((1, 1., 'a'))
tuple 
1
1.0
a
>>> 
fghoussen
  • 393
  • 3
  • 16