C++ boost.python折騰筆記
為了讓當年研究生時寫的圖像處理系統重出江湖起到更大的作用,應研究生導師的意見,對原有的c++框架做了python擴展處理,為了避免遺忘,備註如下:
一、boost 編譯
下載boost源碼,這裏使用boost 1.67,解壓到目錄,進行編譯
- 下載C++的boost庫:http://www.boost.org/
- 安裝Anaconda3-5.1.0-Windows-x86_64 默認路徑安裝
- 解壓boost文件,在其目錄中執行
.\bootstrap.bat
,會生成編譯器b2.exe
和bjam.exe
- 修改
project-config.jam
文件,加入python的版本及路徑(不加入則會默認python2): - import option ;
-
using msvc ;
option.set keep-going : false ;using python
: 3.6 # Version
: C:\\ProgramData\\Anaconda3\\python.exe # Python Path
: C:\\ProgramData\\Anaconda3\\include # include path
: C:\\ProgramData\\Anaconda3\\libs # lib path(s)
- 執行命令(我這裏是vs 2010 故為msvc-10.0)
`.\bjam.exe toolset=msvc-10.0 --with-python threading=multi link=shared address-model=64
,在stage\lib
目錄中會生成boost_numpy3-*
和boost_python3-*
字樣的文件 - 編譯過程遇到了以下問題
- (1)缺少頭文件 無法打開包括文件:“inttypes.h
-
#include<inttypes.h>
編譯時,找不到此文件,所以無法打開
方法:
1. 獲取此文件
2. 放置此文件到目錄:
VS2008,C:\Program Files\Microsoft Visual Studio 9.0\VC\include
VS2010,C:\Program Files\Microsoft Visual Studio 10.0\VC\include - (2)boost 1.67的bug 找不到庫
- C:\Boost\include\boost-1_67\boost\python\numpy\config.hpp
- 修改這一段
-
// enable automatic library variant selection ------------------------------//
#if !defined(BOOST_NUMPY_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_NUMPY_NO_LIB)
//
// Set the name of our library, this will get undef‘ed by auto_link.hpp
// once it‘s done with it:
//
//#define BOOST_LIB_NAME boost_numpy##PY_MAJOR_VERSION##PY_MINOR_VERSION
#define _BOOST_PYTHON_CONCAT(N, M, m) N ## M ## m
#define BOOST_PYTHON_CONCAT(N, M, m) _BOOST_PYTHON_CONCAT(N, M, m)
#define BOOST_LIB_NAME BOOST_PYTHON_CONCAT(boost_numpy, PY_MAJOR_VERSION, PY_MINOR_VERSION)
//
// If we‘re importing code from a dll, then tell auto_link.hpp about it:
//
#ifdef BOOST_NUMPY_DYNAMIC_LIB
# define BOOST_DYN_LINK
#endif
//
// And include the header that does the work:
//
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled#undef BOOST_PYTHON_CONCAT
#undef _BOOST_PYTHON_CONCAT#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#endif // CONFIG_NUMPY20170215_H_
文件C:\Boost\include\boost-1_67\boost\python\detail\config.hpp
#define _BOOST_PYTHON_CONCAT(N, M, m) N ## M ## m
#define BOOST_PYTHON_CONCAT(N, M, m) _BOOST_PYTHON_CONCAT(N, M, m)
#define BOOST_LIB_NAME BOOST_PYTHON_CONCAT(boost_python, PY_MAJOR_VERSION, PY_MINOR_VERSION)
//
// If we‘re importing code from a dll, then tell auto_link.hpp about it:
//
#ifdef BOOST_PYTHON_DYNAMIC_LIB
# define BOOST_DYN_LINK
#endif
//
// And include the header that does the work:
//
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#undef BOOST_PYTHON_CONCAT
#undef _BOOST_PYTHON_CONCAT
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
#define BOOST_PYTHON_SUPPORTS_PY_SIGNATURES // enables smooth transition
#endif
#if !defined(BOOST_ATTRIBUTE_UNUSED) && defined(__GNUC__) && (__GNUC__ >= 4)
# define BOOST_ATTRIBUTE_UNUSED __attribute__((unused))
#endif
二、在VS2010中引用
在 Project
→Project Property
→Configuration Properties
→VC++ Directories
中,Library Directories
中需要包含C:\Boost\lib;C:\ProgramData\Anaconda3\libs;$(LibraryPath);Include Directories
中需要包含C:\Boost\include\boost-1_67;C:\ProgramData\Anaconda3\include;$(IncludePath)
另外要選擇MD多線程。
三、在C++中如何調用python3的腳本
樣例代碼如下:
class ECT_PROCESSOR { public: ECT_PROCESSOR() { Param1=""; Param2=""; Param3=""; Param4=""; Param5=""; Param6=""; Param7=""; Param8=""; Param9=""; Param10=""; dimx=0; dimy=0; dimz=0; } ~ECT_PROCESSOR() { } void SetModel(Model * in_p_model) { p_model=in_p_model; } bool SetSrcValue(int x, int y,int z,int tag, short val) { } short GetSrcValue(int x, int y,int z,int tag) { } bool SetMaskValue(int x, int y,int z, unsigned char val) { } unsigned char GetMaskValue(int x, int y,int z) { } std::string Param1; std::string Param2; std::string Param3; std::string Param4; std::string Param5; std::string Param6; std::string Param7; std::string Param8; std::string Param9; std::string Param10; int dimx; int dimy; int dimz; private: Model *p_model; }; ECT_PROCESSOR* GetECT_PROCESSORInstance() { static ECT_PROCESSOR* the_ECT_PROCESSOR = NULL; if (!the_ECT_PROCESSOR) { the_ECT_PROCESSOR = new ECT_PROCESSOR(); the_ECT_PROCESSOR->SetModel(Model::GetModelInstance()); } return the_ECT_PROCESSOR; } // export c++ function and class to python BOOST_PYTHON_MODULE(MyEngine) { using namespace boost::python; def("GetECT_PROCESSORInstance", GetECT_PROCESSORInstance, return_value_policy< reference_existing_object >()); class_<ECT_PROCESSOR>("ECT_PROCESSOR", "ECT_PROCESSOR") .def("SetSrcValue", &ECT_PROCESSOR::SetSrcValue, args("x", "y","z","tag""val")) .def("GetSrcValue", &ECT_PROCESSOR::GetSrcValue, args("x","y","z","tag")) .def("SetMaskValue", &ECT_PROCESSOR::SetMaskValue, args("x","y","z","val")) .def("GetMaskValue", &ECT_PROCESSOR::GetMaskValue, args("x", "y","z")) .def_readonly("Param1", &ECT_PROCESSOR::Param1,"Param1") .def_readonly("Param2", &ECT_PROCESSOR::Param2,"Param2") .def_readonly("Param3", &ECT_PROCESSOR::Param3,"Param3") .def_readonly("Param4", &ECT_PROCESSOR::Param4,"Param4") .def_readonly("Param5", &ECT_PROCESSOR::Param5,"Param5") .def_readonly("Param6", &ECT_PROCESSOR::Param6,"Param6") .def_readonly("Param7", &ECT_PROCESSOR::Param7,"Param7") .def_readonly("Param8", &ECT_PROCESSOR::Param8,"Param8") .def_readonly("Param9", &ECT_PROCESSOR::Param9,"Param9") .def_readonly("Param10", &ECT_PROCESSOR::Param10,"Param10") .def_readonly("dimx", &ECT_PROCESSOR::dimx,"dimx") .def_readonly("dimy", &ECT_PROCESSOR::dimy,"dimy") .def_readonly("dimz", &ECT_PROCESSOR::dimz,"dimz") ; } bool InitPython() { Py_Initialize(); if(!Py_IsInitialized()) { return false; } return true; } int Controller::ExcutePythonScript_ECT(CString sInFilePath,CString sInFileName,CString sInParam1,CString sInParam2,CString sInParam3,CString sInParam4,CString sInParam5, CString sInParam6,CString sInParam7,CString sInParam8,CString sInParam9,CString sInParam10,CString *pOutMsg) { int tmp_ectindex=model->GetActiveEctIndex(); if(tmp_ectindex<0) { //報錯 OutputLogB("Log.log", __FILE__, __LINE__, "model->GetActiveEctIndex<0"); return -1; } try { CString sModuleName; std::string stdModuleName; std::string stdModulePath(sInFilePath.GetBuffer()); int pos = sInFileName.ReverseFind(‘.‘); if ( pos > 0 ) { sModuleName = sInFileName.Left(pos); stdModuleName=sModuleName.GetBuffer(0); } else { stdModuleName=sInFileName.GetBuffer(0); } std::ifstream fin; char sFullPath[256]={0}; snprintf(sFullPath,sizeof(sFullPath),"%s\\%s",stdModulePath.c_str(),sInFileName.GetBuffer()); OutputLogB("Log.log", __FILE__, __LINE__, "fin.open(%s)",sFullPath); fin.open(sFullPath); std::string str; std::string str_in = ""; while (getline(fin, str)) //一行一行地讀到字符串str_in中 { str_in = str_in + str + ‘\n‘; } fin.close(); using namespace boost::python; if (PyImport_AppendInittab(const_cast<char*>("MyEngine"), #if PY_VERSION_HEX >= 0x03000000 PyInit_MyEngine #else initMyEngine #endif ) == -1) { OutputLogB("Log.log", __FILE__, __LINE__,"Failed to add embedded_hello to the interpreter‘s builtin modules"); return -2; } //PyImport_AppendInittab( stdModuleName.c_str(), &PyInit_MyEngine ); if(!InitPython()) { return -1; } PyInit_MyEngine(); // init MyEngine Module // Add current path to sys.path. You have to // do this in linux. While in Windows, // current path is already in sys.path. ECT_PROCESSOR* pECT_PROCESSOR = GetECT_PROCESSORInstance(); pECT_PROCESSOR->Param1=sInParam1.GetBuffer(); pECT_PROCESSOR->Param2=sInParam2.GetBuffer(); pECT_PROCESSOR->Param3=sInParam3.GetBuffer(); pECT_PROCESSOR->Param4=sInParam4.GetBuffer(); pECT_PROCESSOR->Param5=sInParam5.GetBuffer(); pECT_PROCESSOR->Param6=sInParam6.GetBuffer(); pECT_PROCESSOR->Param7=sInParam7.GetBuffer(); pECT_PROCESSOR->Param8=sInParam8.GetBuffer(); pECT_PROCESSOR->Param9=sInParam9.GetBuffer(); pECT_PROCESSOR->Param10=sInParam10.GetBuffer(); object main_module = import( "__main__" ); object main_namespace = main_module.attr( "__dict__" ); object ignored = exec( "import sys\n" "sys.path.append(‘.‘)\n", main_namespace ); unsigned char maskvalue; if(model->GetactiveMaskindex()>=0&&model->GetActiveMaskValue()==1) { maskvalue=2; model->SetActiveMaskValue(2); } else if(model->GetactiveMaskindex()>=0&&model->GetActiveMaskValue()==0) { maskvalue=1; model->SetActiveMaskValue(1); } else if(model->GetactiveMaskindex()>=0&&model->GetActiveMaskValue()==2) { maskvalue=2; model->SetActiveMaskValue(2); } else { maskvalue=1; model->CreateAndAddBlankMask(); model->SetActiveMaskValue(1); } int dimxyz[3]={0}; model->GetActiveMask()->GetDimensions(dimxyz); pECT_PROCESSOR->dimx=dimxyz[0]; pECT_PROCESSOR->dimy=dimxyz[0]; pECT_PROCESSOR->dimz=dimxyz[0]; object ignored2 = exec(str_in.c_str(), main_namespace); return 0; } catch (boost::python::error_already_set const &) { std::string perror_str = parse_python_exception(); pOutMsg->SetString(perror_str.c_str()); PyErr_Print(); PyErr_Clear(); //delete _module; //_module = NULL; // Py_Finalize(); return -2; } }
C++ boost.python折騰筆記