1. 程式人生 > >C++ boost.python折騰筆記

C++ boost.python折騰筆記

cto rop exec mode pen 字符 cti disable conda

為了讓當年研究生時寫的圖像處理系統重出江湖起到更大的作用,應研究生導師的意見,對原有的c++框架做了python擴展處理,為了避免遺忘,備註如下:

一、boost 編譯

下載boost源碼,這裏使用boost 1.67,解壓到目錄,進行編譯

  • 下載C++的boost庫:
  • 安裝Anaconda3-5.1.0-Windows-x86_64 默認路徑安裝
  • 解壓boost文件,在其目錄中執行.\bootstrap.bat,會生成編譯器b2.exebjam.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中引用

ProjectProject PropertyConfiguration PropertiesVC++ 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折騰筆記