• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            馭風萬里無垠

            用Boost.Python + CMake + wxPython構建跨語言GUI程序<一>

            單純用C/C++做UI程序的盛況已經成為過去時,如果要做跨平臺的UI程序,那么可供選擇的更是為數不多。如果不考慮跨平臺的因素,那么Windows上邊,c#絕對是最佳的選擇,因為微軟的.NET投資大部分在這個上頭,而且有WPF的支持,至少比Java的Swing/SWT/FlashFX要高效和漂亮很多。 如果想跨Posix系統和Windows這兩個平臺,不嫌麻煩的話可以選擇Java (MONO的法律協議還是個問題);但是動態語言的特性決定了它來做界面更有優勢,譬如函數可以隨便做參數傳遞,變量類型可以隨便變換等。

            最近在關注這個方面的東東,恰好就發現了和自己的經驗、興趣很相合的一個選擇:wxWidgets + Python = wxPython.這個項目底層部分是用c++來實現的,基本架構據說和MFC很像,我的那一點可憐的UI經驗都來源于MFC,因此必要的時候查下代碼應該沒大的難度。上層的部分有很多語言的bingding,最成熟的部分則是python綁定的wxPython. 找到了切合點,另外一個問題又隨之而來,UI畢竟只是負責來做用戶交互的,底層的邏輯(網絡、業務)大多還是要c++來寫,或者已經有的C++代碼最好能少改動就可以重復利用。

            突然靈機一動想起來,Boost庫里邊剛還有這么一個東東來處理跨c++ 和 Python 的,可以導出或者內嵌, 于是翻出來體驗一番:

             

            • 編譯Boost.Python

            不經意發現Boost已經有了1.39版本了,我機器上的還是1.37,向來樂于追新的我對于這種自我學習的東西更是不會吝惜時間了,馬上將其7z包拖了下來,居然驚奇的發現里邊已經有了我很喜歡的CMakeLists.txt文件了,原來可以用CMake編譯,boost里邊我最討厭的就是那個bjam了,學了幾次都沒有完全琢磨明白,這次就下定決心也要把CMake版本的編出來。

            這里需要編譯的是libboost_python.so,其它的東西,出于更新的目的,還是把常用的幾個也編一下好了。

            7z x boost_1_39_0.7z
            cd boost_1_39_0/
            mkdir mybuild
            cd mybuild
            cmake ../

            居然報錯了:

            -- ##########################################################################
            --
            --               Only Boost.Build is officially supported.
            --
            --                       This is not Boost.Build.
            --
            --  This is an alternate, cmake-based build system that is currently under development.
            --  To try it out, invoke CMake with the argument
            --         -DCMAKE_IS_EXPERIMENTAL=YES_I_KNOW
            --  Or use the gui to set the variable CMAKE_IS_EXPERIMENTAL to some value.
            --  This will only be necessary the first time.
            --
            --  For more information on boost-cmake see the wiki:
            --      https://svn.boost.org/trac/boost/wiki/CMake
            --
            --  Subscribe to the mailing list:
            --      http://lists.boost.org/mailman/listinfo.cgi/boost-cmake
            --
            --  NOTE:  Please ask questions about this build system on the boost-cmake list,
            --         not on other boost lists.
            --
            --  And/or check the archives:
            --      http://news.gmane.org/gmane.comp.lib.boost.cmake
            --
            -- ##########################################################################

             

            還好問題不大,頂多加上那個選項就是了,有問題自己搞定:

            cmake -DCMAKE_IS_EXPERIMENTAL=YES_I_KNOW ../

            接下來OK了,看看那些選項可以改動,于是ccmake .  , 去掉不需要的variants,將動態庫標上版本號,就是這么幾個:

            BUILD_DEBUG        OFF
            BUILD_STATIC       OFF
            BUILD_VERSIONED    ON

            然后,c/g重新生成cache就可以了。接下來是make,不過照例看一下有哪些可以編, make help之后好大的一堆,這里就選需要的吧:

            make help | grep boost
            ... boost_date_time
            ... boost_date_time-mt-shared
            ... boost_regex
            ... boost_regex-mt-shared
            ... boost_serialization
            ... boost_serialization-mt-shared
            ... boost_wserialization
            ... boost_wserialization-mt-shared
            ... boost_graph
            ... boost_graph-mt-shared
            ... boost_python
            ... boost_python-mt-shared
            ... boost_system
            ... boost_system-mt-shared
            ... boost_prg_exec_monitor
            ... boost_prg_exec_monitor-mt-shared
            ... boost_test_exec_monitor
            ... boost_unit_test_framework
            ... boost_unit_test_framework-mt-shared
            ... boost_filesystem
            ... boost_filesystem-mt-shared
            ... boost_iostreams
            ... boost_iostreams-mt-shared
            ... boost_program_options
            ... boost_program_options-mt-shared
            ... boost_signals
            ... boost_signals-mt-shared
            ... boost_thread
            ... boost_thread-mt-shared
            ... boost_wave
            ... boost_wave-mt-shared

            需要的就是這么幾個了:

            make boost_date_time  boost_regex  boost_python boost_system boost_unit_test_framework boost_filesystem boost_thread  boost_signals

            編譯的過程中,發現有些不對,因為有:

            Linking CXX shared library ../../../lib/libboost_date_time-gcc44-mt-1_38.so

            不是1.39嗎,怎么版本號不對?趕緊查一下 ../CMakeLists.txt,發現:

            grep BOOST_VERSION ../CMakeLists.txt
            set(BOOST_VERSION_MAJOR 1)
            set(BOOST_VERSION_MINOR 38)
            set(BOOST_VERSION_SUBMINOR 0)
            set(BOOST_VERSION "${BOOST_VERSION_MAJOR}.${BOOST_VERSION_MINOR}.${BOOST_VERSION_SUBMINOR}")
            if(BOOST_VERSION_SUBMINOR GREATER 0)
            "include/boost-${BOOST_VERSION_MAJOR}_${BOOST_VERSION_MINOR}_${BOOST_VERSION_SUBMINOR}")
            else(BOOST_VERSION_SUBMINOR GREATER 0)
            "include/boost-${BOOST_VERSION_MAJOR}_${BOOST_VERSION_MINOR}")
            endif(BOOST_VERSION_SUBMINOR GREATER 0)
            #  install(EXPORT boost-targets DESTINATION "lib/Boost${BOOST_VERSION}")
            set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Boost ${BOOST_VERSION}")
            set(CPACK_PACKAGE_VERSION "${BOOST_VERSION}")
            set(CPACK_PACKAGE_VERSION_MAJOR "${BOOST_VERSION_MAJOR}")
            set(CPACK_PACKAGE_VERSION_MINOR "${BOOST_VERSION_MINOR}")
            set(CPACK_PACKAGE_VERSION_PATCH "${BOOST_VERSION_SUBMINOR}")
            set(CPACK_NSIS_DISPLAY_NAME "Boost ${BOOST_VERSION_MAJOR}.${BOOST_VERSION_MINOR}.${BOOST_VERSION_SUBMINOR}")
            set(CPACK_PACKAGE_FILE_NAME "Boost-${BOOST_VERSION}-vc6")
            set(CPACK_PACKAGE_FILE_NAME "Boost-${BOOST_VERSION}-vc7")
            set(CPACK_PACKAGE_FILE_NAME "Boost-${BOOST_VERSION}-vc71")
            set(CPACK_PACKAGE_FILE_NAME "Boost-${BOOST_VERSION}-vc8")
            set(CPACK_PACKAGE_FILE_NAME "Boost-${BOOST_VERSION}-vc9")
            set(CPACK_PACKAGE_FILE_NAME "Boost-${BOOST_VERSION}-borland")
            "http://www.osl.iu.edu/~dgregor/Boost-CMake/${BOOST_VERSION}/"

            將那個38改正成為39就可以了。重復make,生成的庫全在lib目錄下了。

             

            編譯完了之后,才發現make install并不能將這些安裝到系統里邊去,因為它有開始編譯沒有選擇的庫了,真浪費時間,也許這個是它們要堅持其為Experimental Support的緣故吧,而且accumulators庫的編譯還有個問題導致編譯不通過。

            到這里只能再用bjam投機一下,讓它的install命令把頭文件拷貝過去,然后自己手工拷貝庫文件了:

            cd ../
            ./bootstrap
            ./bjam --with-system --libdir=/usr/local/lib threading=multi variant=release link=shared runtime-link=shared toolset=gcc install 
            這里之所以指定libdir是因為默認bjam會將庫文件安裝到/lib/下邊,不知道是不是個bug。好處是只需要指定一個庫的編譯,bjam就可以在install的時間將所有的頭文件準備就緒了。
            查看一下:
            ls -l /usr/local/include/boost-1_39/boost/python

            文件已經在了,再次回到cmake的臨時目錄:

            cd mybuild/lib
            su
            xxxxx
            cp libboost*  /usr/local/lib/
            ls -lh /usr/local/lib/libboost_python-gcc*
            -rwxr-xr-x 1 root root 5.2M 2009-08-09 09:57 /usr/local/lib/libboost_python-gcc44-mt-1_39.so

            OK,boost.python環境準備妥當了,下一步體驗一下其Helloworld。

             

            • 初試Boost.Python<CMake項目>

            新建一個目錄,并用CMake搭建項目環境:

            cd
            mkdir study
            cd study
            mkdir boost.python
            cd boost.python
            mkdir build
            touch CMakeLists.txt
            mkdir HelloWorld

            這里的boost.python作為一個根目錄,build目錄用于編譯和測試,CMakeLists.txt用于組織各個子項目,剩下的就是每個項目一個子目錄了,起步的這個就是boost.python文檔提供的HelloWorld了。根目錄下的CMakeLists.txt如下:

            cmake_minimum_required(VERSION 2.6)
            set(BOOST_INCLUDEDIR /usr/local/include/boost-1_39)
            set(BOOST_LIBRARYDIR /usr/local/lib)
            set(Boost_FIND_VERSION_EXACT TRUE)
            set(Boost_Debug TRUE)
            set(Boost_ADDITIONAL_VERSIONS "1.39" "1.39.0")
            include(FindBoost)
            find_package(Boost 1.39.0 COMPONENTS python thread unit_test_framework)
            if (NOT Boost_FOUND)
            message(FATAL " Boost library not found!")
            endif()
            set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
            set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
            set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
            include_directories(${Boost_INCLUDE_DIRS} /usr/local/include/python2.6/)
            add_subdirectory(HelloWorld)

            中間的一大堆是用于保證能夠找到1.39版本的庫的,因為cmake 2.6.4并不能很好的找到,默認總是找到1.38的,如果沒有安裝多個版本的boost,可能沒有這么麻煩。接下來就是把HelloWorld那個子目錄包進來。

            cd HelloWorld
            cat CMakeLists.txt
            具體內容如下(這里將默認CMake生成的動態庫的lib前綴去掉,因為python不喜歡這個,:-)):
            project(HelloWorld)
            include_directories(${Boost_INCLUDE_DIRS})
            add_library(hello SHARED test.cpp)
            set_target_properties(hello PROPERTIES PREFIX "")
            target_link_libraries(hello ${Boost_LIBRARIES})
            編輯test.cpp,將測試代碼拿進來
            #include <string>
            #include <boost/python.hpp>
            using namespace boost::python;
            struct World
            {
            void set(std::string msg) { this->msg = msg; }
            std::string greet() { return msg; }
            std::string msg;
            };
            //Wrapper
            BOOST_PYTHON_MODULE(hello)
            {
            class_<World>("World")
            .def("greet", &World::greet)
            .def("set", &World::set)
            ;
            }
             
            編譯之:
            cd ../build
            cmake ../
            make
            輸出如下:
            Scanning dependencies of target hello
            [100%] Building CXX object HelloWorld/CMakeFiles/hello.dir/test.cpp.o
            Linking CXX shared library ../lib/hello.so
            [100%] Built target hello
            查看生成的庫文件:
            cd lib
            ls -lh hello.so
            file hello.so

            接下來用測試一番,啟動python:

            python
            ...............
            >>> import hello
            >>> help(hello.World.set)
            Help on method set:
            set(...) unbound hello.World method
            set( (World)arg1, (str)arg2) -> None :
            C++ signature :
            void set(World {lvalue},std::string)
            >>> obj = hello.World()
            >>> obj.set("hello world!")
            >>> obj.greet()
            'hello world!'
            >>> obj.set("Another string")
            >>> obj.greet()
            'Another string'
            >>> del obj
            >>> dir()
            ['__builtins__', '__doc__', '__name__', '__package__', 'hello', 'readline', 'rlcompleter']
            >>> quit()
            

            這里嘗試的幾個方法都已經湊效:構造、析構、greet/set,剛好就是前邊expose的那些了:

            class_<World>("World") .def("greet", &World::greet) .def("set", &World::set) ;

             

            下一步再嘗試一些復雜的東東。

            posted on 2009-08-09 11:34 skyscribe 閱讀(4750) 評論(0)  編輯 收藏 引用

            <2009年10月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            導航

            統計

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            久久精品一区二区国产| 久久99热这里只频精品6| 嫩草影院久久99| 国产L精品国产亚洲区久久| 久久国产精品免费一区二区三区 | 国产精品久久久久国产A级| 国产∨亚洲V天堂无码久久久| 91久久婷婷国产综合精品青草| 999久久久国产精品| 少妇人妻综合久久中文字幕| 国产亚洲精品美女久久久| 国产999精品久久久久久| 久久人妻无码中文字幕| 中文字幕亚洲综合久久| 看久久久久久a级毛片| 久久精品亚洲福利| 久久精品国产亚洲欧美| 国产激情久久久久久熟女老人| 精品久久久久久国产牛牛app| 亚洲AV日韩精品久久久久| 午夜福利91久久福利| 亚洲成人精品久久| 国产精品99久久免费观看| 久久强奷乱码老熟女网站| 深夜久久AAAAA级毛片免费看| 久久亚洲国产午夜精品理论片| 国内高清久久久久久| 日日狠狠久久偷偷色综合0| 日韩欧美亚洲综合久久影院d3| 伊人久久无码中文字幕| 要久久爱在线免费观看| 性欧美大战久久久久久久| 国产精品久久久久乳精品爆 | 人妻丰满?V无码久久不卡| 97久久天天综合色天天综合色hd| 久久久久久曰本AV免费免费| 久久天天日天天操综合伊人av| 久久久久久久亚洲精品| 久久99精品久久久久久不卡| 精品免费久久久久国产一区| 久久91这里精品国产2020|