I am having problems passing back an <std::vector <std::vector <boost::shared_ptr Detection>>> and I was hoping someone could help me out. I am able to pass the vector of vector but when I try and access the Detection, I get a TypeError that there is no python class registered for C++ class boost::shared_ptr which is in the Module definition.
My C++ code is as follows:
class Detection {
public:
Detection () {};
~Detection() {};
double getR () {return r_;};
double getA () {return a_;};
double r_;
double a_;
}
class Detector {
public
std::vector <std::vector <boost::shared_ptr <Detection> > > getDetections();
}
std::vector <std::vector <boost::shared_ptr <Detection> > >
Detector::getDetections () {
std::vector <std::vector <boost::shared_ptr <Detection> > > allVecDetections;
// Build 4 vectors containing 2 detections each
for (unsigned int i=0; i < 4; i++) {
std::vector<boost::shared_ptr<Detection> > vecDetections;
for (unsigned int j = 0; j < 2; j++ ) {
boost::shared_ptr<Detection> dt (new Detection (j+i, ts));
dt->r_ = (j+i) + (j*i);
dt->a_ = (j+i) * (j*i);
vecDetections.push_back (dt);
}
allVecDetections.push_back (vecDetections);
}
return allVecDetections;
}
// Module.cpp
BOOST_PYTHON_MODULE (myModule) {
boost::python::class_<Detector>("Detector")
.def("getDetections", &getDetections)
;
boost::python::class_<Detection>("Detection")
.def("getA", &getA)
.def("getR", &getR)
;
// Map list of Detections
boost::python::class_<std::vector <boost::shared_ptr <Detection> > > ("DetectionVector")
.def(vector_indexing_suite<std::vector <boost::shared_ptr <Detection> > > ());
// Map list of lists of Detections
boost::python::class_<std::vector <std::vector <boost::shared_ptr <Detection> > > > ("DetectionVectorVector")
.def(vector_indexing_suite<std::vector<std::vector <boost::shared_ptr <Detection> > > > ());
// Register our shared pointers with Python
register_ptr_to_python<boost::shared_ptr<Detection> >();
}
I am able to call the getDetections from Python and get back 4 vectors with each one containing 2 Detections. Here is the Python code:
import myModule
...
plots = det.getDetections()
numvectors = len(plots)
print (f'Received {numvectors} vectors ')
jdx = 0
pdx = 0
while jdx < numvectors:
detections = plots[jdx]
pdx = 0
numPlots = len(detections)
print (f'Received {numPlots} extractions')
while pdx < numPlots:
print ("Extraction " + str (pdx) + ":")
detect = detections[jdx]
This runs but I get the following output:
Received 4 vectors
Received 2 extractions
Extraction 0:
Traceback (most recent call last):
File "scripts/test.py", line 87, in <module>
foo = detections[jdx].getA()
TypeError: No Python class registered for C++ class boost::shared_ptr<Detection>
So, why am I getting complaints about Python having no registered class for boost::shared_ptr?
Thanks for any help you can give me. (The above code has been trimmed so typos may have been introduced during the writing of the question).
Taking Valeca's suggestion, I re did the work with passing back a vector<vector> (eliminating the boost::shared_ptr). Now something is unhappy with the module as I seg fault when importing the module in the Pyhton script.
Here are the new changes:
class Detection {
public:
Detection () {};
~Detection() {};
Detection (const Detection &D) {
: r_ (D.r_),
a_ (D.a_)
{};
void operator = (const Detection &D) {
r_ = D.r_;
a_ = D.a_;
};
double getR () {return r_;};
double getA () {return a_;};
double r_;
double a_;
friend bool operator== (const Detection &d1, const Detection &d2);
friend bool operator!= (const Detection &d1, const Detection &d2);
};
bool operator== (const Detection &d1, const Detection &d2) {
return (d1.r_ == d2.r_ && d1.a_ == d2.a_);
}
bool operator!= (const Detection &d1, const Detection &d2) {
return !(d1.r_ == d2.r_ && d1.a_ == d2.a_ );
}
class Detector {
public
std::vector <std::vector <Detection> > getDetections();
}
std::vector <std::vector <Detection> >
Detector::getDetections () {
std::vector <std::vector <Detection> > allVecDetections;
// Build 4 vectors containing 2 detections each
for (unsigned int i=0; i < 4; i++) {
std::vector<Detection> vecDetections;
for (unsigned int j = 0; j < 2; j++ ) {
Detection dt (j+i, ts);
dt.r_ = (j+i) + (j*i);
dt.a_ = (j+i) * (j*i);
vecDetections.push_back (dt);
}
allVecDetections.push_back (vecDetections);
}
return allVecDetections;
}
// Module.cpp
BOOST_PYTHON_MODULE (myModule) {
boost::python::class_<Detector>("Detector")
.def("getDetections", &getDetections)
;
boost::python::class_<Detection>("Detection")
.def("getA", &getA)
.def("getR", &getR)
;
// Map list of Detections
boost::python::class_<std::vector <Detection> > ("DetectionVector")
.def(vector_indexing_suite<std::vector <Detection> > ());
// Map list of lists of Detections
boost::python::class_<std::vector <std::vector<Detection> > > ("DetectionVectorVector")
.def(vector_indexing_suite<std::vector<std::vector <Detection> > > ());
// Register our shared pointers with Python
// register_ptr_to_python<boost::shared_ptr<Detection> >();
}
And now the Python side seg faults on start up. I may have added more overloaded operators than needed but without them, I would see:
*/usr/include/c++/7/bits/predefined_ops.h:241:17: error: no match for ‘operator==’ (operand types are ‘Detection’ and ‘const Detection’) { return __it == _M_value; }
when compiling my module.
Thanks for any light you can shed on this.