2017-05-04 101 views
0

我有一個python嵌入在C++中,C++調用python中的函數,應該返回一個值。這裏是我的Python代碼:Boost Python Python返回值到C++程序

def predict(window, g_slope, g_compliance): 
    ps = model.predict_on_batch(
     x=np.asarray([window]) 
    ) 

    p_slopes = ps[0] 
    p_compliances = ps[1] 
    p_slopes = np.reshape(p_slopes, (np.shape(p_slopes)[1],)) 
    p_compliances = np.reshape(p_compliances, (np.shape(p_compliances)[1],)) 
    p_slope = p_slopes[-1] 
    p_compliance = p_compliances[-1] 

    n_slope = standardize_data(g_slope, means['GROUND_SLOPE'], variances['GROUND_SLOPE']) 
    n_compliance = standardize_data(g_compliance, means['GROUND_STIFFNESS'], variances['GROUND_STIFFNESS']) 

    #print('p_compliance: {0}, n_compliance: {1}, p_slope: {2}, n_slope: {3} '.format(str(p_compliance), str(n_compliance), str(n_slope), str(p_slope))) 

    return(p_slope, n_slope, p_compliance, n_compliance) 

它返回我想在我的C++程序中收到的元組。 我的C++程序調用這樣的功能:

void ContactLearningApp::PythonWorkerThread() { 

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

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

    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); 
     } 
     Data dat = m_data.back(); 
     m_data.pop_back(); 

     ul.unlock(); 

     m_pydata_ptr py_ptr(new PyData); 

     py_ptr->InitWithData(dat); 
     try { 
      bp::tuple results = bp::extract<bp::tuple>(f(bp::ptr(py_ptr.get()))); 
      printf("p_slope: %f, n_slope: %f, p_compliance: %f, n_compliance %f \n", results[0], results[1], results[2], results[3]); 
     } 
     catch (const bp::error_already_set &import) { 
      // Parse and output the exception 
      std::string perror_str = parse_python_exception(); 
      std::cout << "Error in Python: " << perror_str << std::endl; 
     } 
    } 

} 

我試圖從Python中返回的元組,但我得到了以下錯誤消息:

Expecting an object of type tuple; got an object of type NoneType instead. 

我知道這是不是沒有,因爲我能夠正確地訪問每個值的元組。什麼是提取元組的正確方法是什麼?

回答

0

boost::python::object支持operator[]它允許按索引訪問序列(列表,元組等)元素。這意味着你不需要從你的函數返回一個object鑄造成tuple,您可以直接訪問它的元素:

bp::object func = bp::import("my_module").attr("my_func"); 
bp::object foo = func(); 
bp::object bar = foo[0]; 

如果返回Python對象不被索引訪問支持,一個異常會拋出。請注意,您可能仍然需要通過投指數提取到相應的C++類型的序列元素。

通常,您可以將參數從C++「按原樣」傳遞給函數對象,而不會與原始指針PyObject*混淆。 Boost.Python的確實在大多數情況下,必要的轉換。

+0

我試圖從對象中提取這樣的值:'bp :: extract (results [0])'但它給了我一個'NoneType對象不是可下載的錯誤。 – terminix00

+0

以上忽略。但是,我想從這樣的對象中提取值:'BP ::提取(結果[0])'但它給我的一個0.00000值,這是出乎我的Python腳本是什麼打印。 – terminix00