将C++对象实例传递给Python函数

2024-05-15 17:21:20 发布

您现在位置:Python中文网/ 问答频道 /正文

为了得到一个对象并在返回结果之前用python处理它,我有一个对象队列。我有点不确定它是如何结合在一起的,但从我从各个地方收集的资料来看,我觉得我已经很接近了。在

我有一节课是这样的:

class PyData
{
public:

    PyData(
        const btVector3 &TORSO_LV,
        std::vector<std::tuple<float, float, float>> DsOsAVs,
        std::vector<btVector3> RF_FORCES,
        std::vector<btVector3> LF_FORCES,
        float slope,
        float compliance
        );

    std::tuple<float, float, float> m_TORSO_LV;
    std::vector<std::tuple<float, float, float>> m_DsOsAVS;
    std::vector<std::tuple<float, float, float>> m_RF_FORCES;
    std::vector<std::tuple<float, float, float>> m_LF_FORCES;

    float m_slope;
    float m_compliance;


    ~PyData();
};

然后我创建了一个boost python模块,如下所示:

^{pr2}$

每隔33毫秒,我创建一个PyData对象并将其放入队列中。像这样:

// Check the sample clock for sampling
    if (m_sampleClock.getTimeMilliseconds() > 33) {
        if (ContactManager::GetInstance().m_beingUsed) {
            PyData dat = BuildPyData();
            if (dat.m_compliance != 0.0f) {
                std::unique_lock <std::mutex> l(m_mutex);
                m_data.push_front(dat);
                m_NotEmptyCV.notify_one();
                l.unlock();
            }
        }

        m_sampleClock.reset();
    }

然后,我有一个单独的工作线程,该线程将队列出列以获取对象并将其发送到一个python函数,该函数如下所示:

void ContactLearningApp::PythonWorkerThread() {

    printf("Start Python thread. \n");

    bp::object f = m_interface.attr("predict_on_data");

    while (true) {
        //printf("Inside while loop and waiting. \n");
        std::unique_lock<std::mutex> ul(m_mutex);
        while (m_data.size() <= 0) {
            m_NotEmptyCV.wait(ul);
        }
        PyData dat = m_data.back();
        m_data.pop_back();

        f(boost::python::ptr(&dat));

        ul.unlock();
        //m_ProcessedCV.notify_one();
        //bp::exec("print ('Hello from boost')", m_main_namespace);
    }

}

基本上,我试图传递一个用c++实例化的对象作为python参数,但是我不知道如何将它拼凑在一起。python解释器不需要对象的副本,所以我使用boost::python::ptr。 python文件很简单,我只想将接收到的对象打印到控制台上,如下所示:

def predict_on_data(data):
    print("In Predict on Data")
    print(data)

我不确定这是如何与增压模块集成的。正确的方法是什么?在


Tags: 对象dataif队列floatdatpydatastd
1条回答
网友
1楼 · 发布于 2024-05-15 17:21:20

我已经编写了一些基于PyData数据对象的示例代码;这段代码使用boost::python数据结构(tuple和list)来与python交换数据,因为这是它们的预期用途,但是可以根据需要将数据从std::tuple和std::vector复制到它们中来填充这些数据。在

这适用于Python2.7和boost 1.53。希望您可以使用它来帮助;NB Py_initialize()之后需要调用initpydata()(生成的函数)。在

C++代码:

#include <iostream>
#include <vector>
#include <tuple>
#include <boost/python.hpp>
#include <boost/python/list.hpp>

class PyData
{
    public:

    PyData() {}

    float m_slope;
    float m_compliance;

    boost::python::tuple    m_TORSO_LV;
    boost::python::list     m_DsOsAVS;
    boost::python::list     m_RF_FORCES;
    boost::python::list     m_LF_FORCES;

    void InitData()
    {
        // simulate setting up data
        m_slope = 1.0;
        m_compliance = 2.0;

        m_TORSO_LV = boost::python::make_tuple(3.0, 4.0, 5.0);

        m_DsOsAVS.append(boost::python::make_tuple(10.0, 11.0, 12.0));
        m_DsOsAVS.append(boost::python::make_tuple(20.0, 21.0, 22.0));

        // etc.
    }

    ~PyData() {}
};

BOOST_PYTHON_MODULE(pydata) {
boost::python::class_<PyData>("PyData")
    .def_readwrite("Torso_LV", &PyData::m_TORSO_LV)
    .def_readwrite("DsOsAVs", &PyData::m_DsOsAVS)
    .def_readwrite("RF_FORCES", &PyData::m_RF_FORCES)
    .def_readwrite("LF_FORCES", &PyData::m_LF_FORCES)
    .def_readwrite("slope", &PyData::m_slope)
    .def_readwrite("compliance", &PyData::m_compliance)
    ;
};

int main (int argc, char * argv[])
{
    Py_Initialize();

    initpydata();

    boost::python::object main=boost::python::import("__main__");
    boost::python::object global(main.attr("__dict__"));
    boost::python::object result = boost::python::exec_file("/home/andy/Python2.py", global, global);
    boost::python::object predict_on_data = global["predict_on_data"];
    if (!predict_on_data.is_none())
    {
        boost::shared_ptr<PyData> o(new PyData);
        o->InitData();
        predict_on_data(boost::python::ptr(o.get()));
        std::cout << "values in c++ object are now: " << o->m_slope << " and " << o->m_compliance << std::endl;
    }

    return 0;
}

Python代码(本例中为Python2.py文件):

^{pr2}$

一旦运行,输出如下:

In Python:
<pydata.PyData object at 0x7f41200956e0>
o.slope is 1.0
o.compliance is 2.0
o.Torso_LV is (3.0, 4.0, 5.0)
o.m_DsOsAVs is [(10.0, 11.0, 12.0), (20.0, 21.0, 22.0)]
values in c++ object are now: -1 and -2

希望这是有用的。在

相关问题 更多 >