2017-04-24 14 views
0

オブジェクトを取得して結果を返す前にPythonで処理するために、デキューするオブジェクトのキューがあります。私はそれがどのように一緒に収まるのか少し分かりませんが、私がかなり近くにいると思う様々な場所から集まったものから、私は少し分かります。C++オブジェクトインスタンスを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(); 
}; 

をしてから、私はこのようになりますブーストのpythonモジュールを作成:私はPyDataオブジェクトを作成し、すべての33ミリ秒後

BOOST_PYTHON_MODULE(pydata) { 
    bp::class_<PyData>("PyData", 
     bp::init< 
      const btVector3, 
      std::vector<std::tuple<float, float, float>>, 
      std::vector<btVector3>, 
      std::vector<btVector3>, 
      float, 
      float 
     >()) 
     .def_readonly("Torso_LV", &PyData::m_TORSO_LV) 
     .def_readonly("DsOsAVs", &PyData::m_DsOsAVS) 
     .def_readonly("RF_FORCES", &PyData::m_RF_FORCES) 
     .def_readonly("LF_FORCES", &PyData::m_LF_FORCES); 
}; 

をし、それをキューに入れます。このような何か:

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

} 

を、私がしようとしていますPythonの引数としてC++でインスタンス化されたオブジェクトを渡すことができますが、どのように一緒に分割するのか分かりません。私はboost :: python :: ptrを使用しているので、Pythonインタプリタはオブジェクトのコピーを必要としません。このようなコンソール上で受信 Pythonのファイルはシンプルで、私はちょうどオブジェクトを印刷したい:

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

私は、これはブーストモジュールと統合するかどうかはわかりません。これを行う正しい方法は何でしょうか?

答えて

0

私はあなたのPyDataデータオブジェクトに基づいていくつかのサンプルコードを書いています。このコードでは、Pythonとのデータのやり取りにboost :: pythonのデータ構造(タプルとリスト)を使用していますが、これは意図した使い方なので、データをstd :: tupleとstd :: vector必要に応じて。

これはPython 2.7およびboost 1.53で動作します。うまくいけば、あなたはこれを助けるために使うことができます。注意:Py_Initialze()の後に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ファイル):

def predict_on_data(o): 
    print "In Python:" 
    print repr(o) 
    # print the data members in o 
    print "o.slope is " + repr(o.slope) 
    print "o.compliance is " + repr(o.compliance) 
    print "o.Torso_LV is " + repr(o.Torso_LV) 
    print "o.m_DsOsAVs is " + repr(o.DsOsAVs) 
    # modify some data 
    o.slope = -1.0 
    o.compliance = -2.0 

いったんこれがこのような出力を与える必要が実行されている:

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 

ホープこれは便利です。

+0

initpydata()関数が見つかりません。私は、ドキュメントがinitname()とinit_module_name()を生成するので、自動的に生成されることを知っています。私はinit_module_pydata()を見つけることができます。彼らは同じことですか? init_nameは、init_module_nameをC++のhandle_exception()に渡すだけです。 – terminix00

+0

私の例のC++コードでは、initpydata()関数が(マクロを介して)作成され、BOOST_PYTHON_MODULE(pydata)で始まるコードブロックによってスコープに持ち込まれます。もしそうなら、それはそこにあるはずです。 –

関連する問題