어떻게 Boost.Python 을 이용 하여 Python C/C++혼합 프로 그래 밍 을 실현 합 니까?

머리말
학습 중 문제 가 발생 하면 홈 페이지 의 예 를 참고 하 세 요.
D:\boost_1_61_0\libs\python\test
참고:Boost.Python 의 영문 문서 입 니 다.
Boost.Python 을 이용 하여 Python C/C++혼합 프로 그래 밍 을 실현 합 니 다.
python 과 C++혼합 프로 그래 밍 에 대해 서 는 사실상 두 부분 이 있 습 니 다.
  • extending 이른바 python 프로그램 에서 c/c+코드 를 호출 합 니 다.사실은 c+코드 를 먼저 처리 하고 미리 생 성 된 동적 링크 라 이브 러 리 입 니 다.예 를 들 어 example.so,python 코드 에서 import example;c/c++의 함 수 를 사용 할 수 있 습 니 다.
  • embedding c+코드 에서 python 코드 를 호출 합 니 다.
  • 둘 다 python c 로 api 를 변환 하여 해결 할 수 있 습 니 다.구체 적 으로 python 공식 문 서 를 찾 아 볼 수 있 지만 모두 번 거 롭 습 니 다.
    1.extending 에 있어 서 자주 사용 하 는 방안 은 boost.python 과 swig 입 니 다.
    swig 는 접착 C++,PYTHON 입 니 다.제 앞 에 있 는 도형 에 이 진 트 리 를 표시 하 는 글 에서 언급 한 것 은 pyqt 를 인터페이스 로 하고 c+코드 를 사용 하여 swig 로 생 성 된.so 동적 라 이브 러 리 입 니 다.
    boost.python 은 직접 전환 하여 py++를 이용 하여 필요 한 wrapper 를 자동 으로 생 성 할 수 있 습 니 다.이 방면 의 내용 에 대한 입문 은 boost.python 홈 페이지 를 제외 하고 중국어 입문 자 료 를 추천 합 니 다.
    다음은 더 이상 할 말 이 없 으 니 상세 한 소 개 를 살 펴 봅 시다.
    내 보 내기 함수
    
    #include<string>
    #include<boost/python.hpp>
    
    using namespace std;
    using namespace boost::python;
    
    
    char const * greet()
    {
     return "hello,world";
    
    }
    
    BOOST_PYTHON_MODULE(hello_ext)
    {
     def("greet", greet);
    }
    python:
    
    import hello_ext
    print hello_ext.greet()
    내 보 내기 클래스:
    기본 구조의 함수 클래스 내 보 내기
    c++
    
    #include<string>
    #include<boost/python.hpp>
    
    using namespace std;
    using namespace boost::python;
    
    struct World
    {
     void set(string msg) { this->msg = msg; }
     string greet() { return msg; }
    
     string msg;
    };
    
    BOOST_PYTHON_MODULE(hello) //   module   
    {
     class_<World>("World")
     .def("greet", &World::greet)
     .def("set", &World::set);
    }
    python:
    
    import hello 
    planet = hello.World() #         ,     
    planet.set("howdy") #        
    print planet.greet() #        
    구조 함수 내 보 내기:
    
    #include<string>
    #include<boost/python.hpp>
    
    using namespace std;
    using namespace boost::python;
    
    struct World
    {
     World(string msg):msg(msg){} //      
     World(double a, double b):a(a),b(b) {} //        
     void set(string msg) { this->msg = msg; }
     string greet() { return msg; }
     double sum_s() { return a + b; }
     string msg;
     double a;
     double b;
    };
    
    BOOST_PYTHON_MODULE(hello) //   module   
    {
     class_<World>("World",init<string>()) 
     .def(init<double,double>()) // expose another construct
     .def("greet", &World::greet)
     .def("set", &World::set)
     .def("sum_s", &World::sum_s);
    }
    python 테스트 호출:
    
    import hello
    planet = hello.World(5,6)
    planet2 = hello.World("hollo world")
    
    print planet.sum_s()
    print planet2.greet()
    구조 함 수 를 내 보 내지 않 으 려 면 no 를 사용 하 십시오.init:
    
    class_<Abstract>("Abstract",no_init)
    클래스 데이터 멤버
    
    #include<string>
    #include<boost/python.hpp>
    
    using namespace std;
    using namespace boost::python;
    
    
    struct Var
    {
     Var(string name):name(name),value(){}
     string const name;
    
     float value;
    };
    
    BOOST_PYTHON_MODULE(hello_var)
    {
     class_<Var>("Var", init<string>())
     .def_readonly("name", &Var::name) //  
     .def_readwrite("value", &Var::value); //  
    }
    python 호출:
    
    import hello_var
    
    var = hello_var.Var("hello_var")
    var.value = 3.14
    # var.name = 'hello' # error
    print var.name
    C++클래스 대상 을 Python 의 클래스 대상 으로 내 보 냅 니 다.var.name 에서 값 을 부여 할 수 없 음 을 주의 하 십시오.
    클래스 속성
    
    //     
    
    #include<string>
    #include<boost/python.hpp>
    
    using namespace std;
    using namespace boost::python;
    
    
    struct Num
    {
     Num(){}
     float get() const { return val; }
     void set(float val) { this->val = val; }
     float val;
    
    };
    
    BOOST_PYTHON_MODULE(hello_num)
    {
     class_<Num>("Num")
     .add_property("rovalue", &Num::get) //   :  
     .add_property("value", &Num::get, &Num::set);//      .value    .rovalue ,        。
    
    }
    python:
    
    import hello_num
    num = hello_num.Num()
    num.value = 10
    print num.rovalue # result: 10
    이어받다
    
    //     
    
    #include<string>
    #include<iostream>
    #include<boost/python.hpp>
    
    using namespace std;
    using namespace boost::python;
    
    struct Base {
     virtual ~Base() {};
     virtual string getName() { return "Base"; }
    
     string str;
    };
    
    struct Derived : Base {
    
     string getName() { return "Derived"; }
    
    };
    
    
    void b(Base *base) { cout << base->getName() << endl; };
    
    void d(Derived *derived) { cout << derived->getName() << endl; };
    
    Base * factory() { return new Derived; }
    
    /*
                    。
         :http://stackoverflow.com/questions/38261530/unresolved-external-symbols-since-visual-studio-2015-update-3-boost-python-link/38291152#38291152
    */
    namespace boost
    {
     template <>
     Base const volatile * get_pointer<class Base const volatile >(
     class Base const volatile *c)
     {
     return c;
     }
    }
    
    
    BOOST_PYTHON_MODULE(hello_derived)
    {
     class_<Base>("Base")
     .def("getName", &Base::getName)
     .def_readwrite("str", &Base::str);
    
    
     class_<Derived, bases<Base> >("Derived")
     .def("getName", &Derived::getName)
     .def_readwrite("str", &Derived::str);
    
    
     def("b", b);
     def("d", d);
    
     def("factory", factory,
     return_value_policy<manage_new_object>());//
    
    }
    python:
    
    import hello_derived
    derive = hello_derived.factory()
    hello_derived.d(derive)
    클래스 의 가상 함수:
    
    /*
          ,      :    Python ,   C++ 
    */
    #include<boost/python.hpp>
    
    #include<boost/python/wrapper.hpp>
    #include<string>
    #include<iostream>
    
    using namespace boost::python;
    using namespace std;
    
    struct Base
    {
     virtual ~Base() {}
     virtual int f() { return 0; };
    };
    
    
    struct BaseWrap : Base, wrapper<Base>
    {
     int f()
     {
     if (override f = this->get_override("f"))
      return f(); //         ,      
     return Base::f(); //      
     }
     int default_f() { return this->Base::f(); }
    };
    
    BOOST_PYTHON_MODULE(hello_virtual)
    {
     class_<BaseWrap, boost::noncopyable>("Base")
     .def("f", &Base::f, &BaseWrap::default_f);
    
    
    }
    python:
    
    import hello_virtual
    
    
    base = hello_virtual.Base()
    #      ,  C++ 
    class Derived(hello_virtual.Base):
     def f(self):
     return 42
    
    derived = Derived()
    
    
    print base.f()
    
    print derived.f()
    클래스 연산 자/특수 함수
    
    //      /    
    
    #include<string>
    #include<iostream>
    
    
    // #include<boost/python.hpp>          ,   
    
    #include <boost/python/operators.hpp>
    #include <boost/python/class.hpp>
    #include <boost/python/module.hpp>
    #include <boost/python/def.hpp>
    #include <boost/operators.hpp>
    
    using namespace std;
    using namespace boost::python;
    
    class FilePos
    {
    public:
     FilePos() :len(0) {}
     operator double()const { return len; };//       
     int len;
    };
    
    // operator   
    
    FilePos operator+(FilePos pos, int a)
    {
     pos.len = pos.len + a;
    
     return pos; //      
    
    }
    
    FilePos operator+(int a, FilePos pos)
    {
     pos.len = pos.len + a;
    
     return pos; //      
    
    }
    
    
    int operator-(FilePos pos1, FilePos pos2)
    {
    
     return (pos1.len - pos2.len);
    
    }
    
    FilePos operator-(FilePos pos, int a)
    {
     pos.len = pos.len - a;
     return pos;
    }
    
    FilePos &operator+=(FilePos & pos, int a)
    {
     pos.len = pos.len + a;
     return pos;
    }
    
    FilePos &operator-=(FilePos & pos, int a)
    {
     pos.len = pos.len - a;
     return pos;
    }
    
    bool operator<(FilePos pos1, FilePos pos2)
    {
     if (pos1.len < pos2.len)
     return true;
     return false;
    }
    
    
    //     
    
    FilePos pow(FilePos pos1, FilePos pos2)
    {
     FilePos res;
     res.len = std::pow(pos1.len, pos2.len);
     return res;
    
    }
    FilePos abs(FilePos pos)
    {
     FilePos res;
     res.len = std::abs(pos.len);
    
     return res;
    }
    
    ostream& operator<<(ostream& out, FilePos pos)
    {
     out << pos.len;
     return out;
    }
    
    BOOST_PYTHON_MODULE(hello_operator)
    {
     class_<FilePos>("FilePos")
     .def_readwrite("len",&FilePos::len)
     .def(self + int())
     .def(int() + self)
     .def(self - self)
     .def(self - int())
     .def(self += int())
     .def(self -= other<int>())
     .def(self < self)
     .def(float_(self))//     , __float__
     .def(pow(self, other<FilePos>())) // __pow__
     .def(abs(self))  // __abs__
     .def(str(self));  // __str__ for ostream
    
    
    }
    위의:def(pow(self,other())템 플 릿 뒤에 괄호 를 붙 여야 합 니 다.헤더 파일 의 포함 에 도 주의해 야 합 니 다.그렇지 않 으 면 오류 가 발생 할 수 있 습 니 다.
    python:
    
    import hello_operator
    
    filepos1 = hello_operator.FilePos()
    filepos1.len = 10
    
    filepos2 = hello_operator.FilePos()
    filepos2.len = 20;
    
    print filepos1 - filepos2
    함수.
    함수 호출 정책.
    
    //        
    
    #include<string>
    #include<iostream>
    
    #include<boost/python.hpp>
    
    using namespace std;
    using namespace boost::python;
    
    struct X
    {
     string str;
    };
    struct Z
    {
     int value;
    };
    
    struct Y
    {
     X x;
     Z *z;
     int z_value() { return z->value; }
    };
    
    X & f(Y &y, Z*z)
    {
     y.z = z;
     return y.x; //  x y     ,x      y     。        :Python         C++  
    }
    
    
    BOOST_PYTHON_MODULE(hello_call_policy)
    {
    
     class_<Y>("Y")
     .def_readwrite("x", &Y::x)
     .def_readwrite("z", &Y::z)
     .def("z_value", &Y::z_value);
     class_<X>("X")
     .def_readwrite("str", &X::str);
     class_<Z>("Z")
     .def_readwrite("value", &Z::value);
     // return_internal_reference<1                :               (y x       )。
     // with_custodian_and_ward<1, 2>                          。
     def("f", f, return_internal_reference<1, with_custodian_and_ward<1, 2> >());
    }
    함수 과부하
    
    // overloading
    
    #include<string>
    #include<iostream>
    
    #include<boost/python.hpp>
    
    using namespace std;
    using namespace boost::python;
    
    struct X
    {
    
     bool f(int a)
     {
     return true;
     }
     bool f(int a, double b)
     {
     return true;
     }
     bool f(int a, double b, char c)
     {
     return true;
     }
     int f(int a, int b, int c)
     {
     return a + b + c;
     }
    };
    bool (X::*fx1)(int) = &X::f;
    bool(X::*fx2)(int, double) = &X::f;
    bool(X::*fx3)(int, double,char) = &X::f;
    int(X::*fx4)(int, int,int) = &X::f;
    
    BOOST_PYTHON_MODULE(hello_overloaded)
    {
     class_<X>("X")
     .def("f", fx1)
     .def("f", fx2)
     .def("f", fx3)
     .def("f", fx4);
    
    }
    python:
    
    import hello_overloaded
    
    x = hello_overloaded.X() # create a new object
    
    
    print x.f(1) # default int type
    print x.f(2,double(3))
    print x.f(4,double(5),chr(6)) # chr(6) convert * to char 
    print x.f(7,8,9)
    기본 매개 변수
    일반 함수 의 기본 매개 변수:
    그러나 위 에서 재 부팅 함 수 를 봉인 할 때 기본 매개 변수 에 대한 정 보 를 잃 어 버 렸 습 니 다.물론 우 리 는 일반적인 형식의 포장 을 통 해 다음 과 같다.
    
    int f(int,double = 3.14,char const * = "hello");
    int f1(int x){ return f(x);}
    int f2(int x,double y){return f(x,y)}
    
    //int module init
    def("f",f); //     
    def("f",f2); //    
    def("f",f1); //    
    하지만 위의 형식 으로 포장 하 는 것 은 번거롭다.우 리 는 매크로 형식 을 통 해 위의 기능 을 대량으로 완성 할 수 있다.
    C++:
    
    // BOOST_PYTHON_FUNCTION_OVERLOADS
    
    #include<string>
    #include<iostream>
    
    #include<boost/python.hpp>
    
    
    using namespace std;
    using namespace boost::python;
    
    
    void foo(int a, char b = 1, unsigned c = 2, double d = 3)
    {
     return;
    }
    
    BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 1, 4); //         1,   4
    
    BOOST_PYTHON_MODULE(hello_overloaded)
    {
    
     def("foo", foo, foo_overloads()); //             
    
    }
    
    python:
    
    import hello_overloaded
    
    
    hello_overloaded.foo(1)
    
    hello_overloaded.foo(1,chr(2))
    
    hello_overloaded.foo(1,chr(2),3) # 3   C++ unsigned int
    
    hello_overloaded.foo(1,chr(2),3,double(4))
    구성원 함수 의 기본 매개 변수:
    
    //  BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS  ,             
    
    #include<string>
    #include<iostream>
    
    #include<boost/python.hpp>
    
    
    using namespace std;
    using namespace boost::python;
    
    struct george
    {
     void wack_em(int a, int b = 0, char c = 'x')
     {
      return;
     }
    
    };
    
    
    BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(george_overloads, wack_em, 1, 3); //         1,   3
    
    BOOST_PYTHON_MODULE(hello_member_overloaded)
    {
    
     class_<george>("george")
      .def("wack_em", &george::wack_em, george_overloads());
    
    }
    python:
    
    import hello_member_overloaded
    
    c = hello_member_overloaded.george()
    
    c.wack_em(1)
    c.wack_em(1,2)
    c.wack_em(1,2,chr(3))
    init 와 optional 을 이용 하여 구조 함수 의 재 부팅 을 실현 합 니 다.
    사용 방법 은 다음 과 같다.
    
    // init optional
    
    #include<string>
    #include<iostream>
    #include<boost/python.hpp>
    
    using namespace std;
    using namespace boost::python;
    
    struct X
    {
     X(int a, char b = 'D', string c = "constructor", double b = 0.0) {}
    };
    
    BOOST_PYTHON_MODULE(hello_construct_overloaded)
    {
     class_<X>("X")
      .def(init<int, optional<char, string, double> >()); // init   optional
    
    }
    대상 인터페이스
    Python 은 동적 형식의 언어 이 고 C++는 정적 형식 입 니 다.Python 변 수 는 integer,float,list,dict,tuple,str,long 등 이 고 다른 유형 이 있 을 수 있 습 니 다.Boost.Python 과 C++의 관점 에서 볼 때 Python 의 변 수 는 클래스 object 의 인 스 턴 스 입 니 다.이 절 에서 Python 대상 을 어떻게 처리 하 는 지 보 겠 습 니 다.
    기본 인터페이스
    
    // init optional
    
    #include<string>
    #include<iostream>
    #include<boost/python.hpp>
    #include <numpy/arrayobject.h>
    using namespace std;
    using namespace boost::python;
    
    namespace bp = boost::python;
    
    
    void f(object x)
    {
     int y = extract<int>(x); // retrieve an int from x
    
    }
    
    int g(object x)
    {
     extract<int> get_int(x);
     if (get_int.check())
      return get_int();
     else
      return 0;
    }
    
    
    int test(object &x)
    {
     dict d = extract<dict>(x.attr("__dict__"));
     d["whatever"] = 4;
     return 0;
    }
    
    int test2(dict & d)
    {
     d["helloworld"] = 3;
     return 0;
    }
    class A {
    
    public:
     list lst;
     void listOperation(list &lst) {};
    };
    
    //   np.array    , C++    
    int add_arr_1(object & data_obj, object rows_obj, object cols_obj)
    {
     PyArrayObject* data_arr = reinterpret_cast<PyArrayObject*>(data_obj.ptr());
     float * data = static_cast<float *>(PyArray_DATA(data_arr));
     // using data
     int rows = extract<int>(rows_obj);
     int cols = extract<int>(cols_obj);
     for (int i = 0; i < rows*cols; i++)
     {
      data[i] += 1;
     }
     return 0;
    
    }
    BOOST_PYTHON_MODULE(hello_object)
    {
     def("test", test);
     def("test2", test2);
     def("add_arr_1", add_arr_1);
    }
    python 호출:
    
    import hello_object
    
    dic1 = {"whatever":1}
    
    hello_object.test2(dic1)
    
    arr = np.array([1,2,3],dtype = float32)
    
    print arr.dtype
    
    print arr
    
    hello_object.add_arr_1(arr,1,3)
    
    print arr
    요약:
    이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기