【问题标题】:Problems passing a std::vector of vector of boost::shared_ptrs from C++ to Python将 boost::shared_ptrs 的向量的 std::vector 从 C++ 传递到 Python 的问题
【发布时间】:2021-06-16 07:34:14
【问题描述】:

我在传回 <:vector detection>>> 时遇到问题,我希望有人能帮助我。我能够传递向量的向量,但是当我尝试访问 Detection 时,我得到一个 TypeError,表明没有为模块定义中的 C++ 类 boost::shared_ptr 注册 python 类。

我的C++代码如下:

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> >(); 
  
}

我可以从 Python 调用 getDetections 并返回 4 个向量,每个向量包含 2 个检测。这是 Python 代码:

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]

这会运行,但我得到以下输出:

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>  

那么,为什么我会抱怨 Python 没有为 boost::shared_ptr 注册的类?

感谢您能给我的任何帮助。 (上面的代码已经被修剪,所以在写问题的过程中可能引入了拼写错误)。

接受 Valeca 的建议,我重新完成了传回 vector 的工作(消除了 boost::shared_ptr)。现在模块有些不满意,因为我在 Pyhton 脚本中导入模块时出现了段错误。

以下是新变化:

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> >(); 

}

现在 Python 端 seg 在启动时出现错误。我可能添加了比需要更多的重载运算符,但没有它们,我会看到:

*/usr/include/c++/7/bits/predefined_ops.h:241:17:错误:'operator==' 不匹配(操作数类型为'Detection'和'const Detection ') { 返回 __it == _M_value; }

在编译我的模块时。

感谢您对此提供的任何启发。

【问题讨论】:

  • 我看不出使用共享指针的原因。你能解释一下你为什么使用它们吗?您是否尝试将向量定义为 std::vector vecDetections 并推回对象?最好避免使用向量作为向量本身的项。
  • 根据您的建议,我也尝试了它 vector> 这还需要在 Detection 类上实现 ==, != = 运算符(在编译时在 Module. cpp 没有它)。当我现在运行时,我在加载模块之前出现了段错误,这通常意味着 Python 不知道如何实例化我的向量。所以我必须遗漏一些必需的重载方法,以便 Python 知道收到后要做什么。这就是我开始使用 shared_ptr 的原因之一。
  • 在某种程度上与您最初使用 shared_ptr stackoverflow.com/questions/5055443/… 遇到的问题类似。
  • 我想是的。我能够使用 boost::shared_ptr 将对象从 C++ 传递回 Python,并让它按预期工作。我还可以传回一个 vector>> 并按预期工作。我不确定为什么 boost::shared_ptr 或检测类有问题 - 我唯一能想到的是我在模块定义中缺少一个 kep 映射。

标签: python c++ vector shared-ptr boost-python


【解决方案1】:

我使用 vector > 事实证明,当我注册我的向量时,我错过了 NoProxy 覆盖。请参阅 Module.cpp 中的固定代码。

    boost::python::class_<std::vector <boost::shared_ptr <Detection> > > ("DetectionVector")
        .def(vector_indexing_suite<std::vector <boost::shared_ptr <Detection> >,true > ());

    // 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> > >, true > ());


我记得看到有关此问题的 Stack Overflow 消息,其中作者说真实情况非常重要。确实如此。感谢所有提供建议的人。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    • 2013-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多