• <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>

            馭風(fēng)萬(wàn)里無(wú)垠

            用Boost.Python + CMake + wxPython構(gòu)建跨語(yǔ)言GUI程序<一>

            單純用C/C++做UI程序的盛況已經(jīng)成為過(guò)去時(shí),如果要做跨平臺(tái)的UI程序,那么可供選擇的更是為數(shù)不多。如果不考慮跨平臺(tái)的因素,那么Windows上邊,c#絕對(duì)是最佳的選擇,因?yàn)槲④浀?NET投資大部分在這個(gè)上頭,而且有WPF的支持,至少比Java的Swing/SWT/FlashFX要高效和漂亮很多。 如果想跨Posix系統(tǒng)和Windows這兩個(gè)平臺(tái),不嫌麻煩的話可以選擇Java (MONO的法律協(xié)議還是個(gè)問(wèn)題);但是動(dòng)態(tài)語(yǔ)言的特性決定了它來(lái)做界面更有優(yōu)勢(shì),譬如函數(shù)可以隨便做參數(shù)傳遞,變量類型可以隨便變換等。

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

            突然靈機(jī)一動(dòng)想起來(lái),Boost庫(kù)里邊剛還有這么一個(gè)東東來(lái)處理跨c++ 和 Python 的,可以導(dǎo)出或者內(nèi)嵌, 于是翻出來(lái)體驗(yàn)一番:

             

            • 編譯Boost.Python

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

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

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

            居然報(bào)錯(cuò)了:

            -- ##########################################################################
            --
            --               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
            --
            -- ##########################################################################

             

            還好問(wèn)題不大,頂多加上那個(gè)選項(xiàng)就是了,有問(wèn)題自己搞定:

            cmake -DCMAKE_IS_EXPERIMENTAL=YES_I_KNOW ../

            接下來(lái)OK了,看看那些選項(xiàng)可以改動(dòng),于是ccmake .  , 去掉不需要的variants,將動(dòng)態(tài)庫(kù)標(biāo)上版本號(hào),就是這么幾個(gè):

            BUILD_DEBUG        OFF
            BUILD_STATIC       OFF
            BUILD_VERSIONED    ON

            然后,c/g重新生成cache就可以了。接下來(lái)是make,不過(guò)照例看一下有哪些可以編, 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

            需要的就是這么幾個(gè)了:

            make boost_date_time  boost_regex  boost_python boost_system boost_unit_test_framework boost_filesystem boost_thread  boost_signals

            編譯的過(guò)程中,發(fā)現(xiàn)有些不對(duì),因?yàn)橛校?/p>

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

            不是1.39嗎,怎么版本號(hào)不對(duì)?趕緊查一下 ../CMakeLists.txt,發(fā)現(xiàn):

            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}/"

            將那個(gè)38改正成為39就可以了。重復(fù)make,生成的庫(kù)全在lib目錄下了。

             

            編譯完了之后,才發(fā)現(xiàn)make install并不能將這些安裝到系統(tǒng)里邊去,因?yàn)樗虚_始編譯沒有選擇的庫(kù)了,真浪費(fèi)時(shí)間,也許這個(gè)是它們要堅(jiān)持其為Experimental Support的緣故吧,而且accumulators庫(kù)的編譯還有個(gè)問(wèn)題導(dǎo)致編譯不通過(guò)。

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

            cd ../
            ./bootstrap
            ./bjam --with-system --libdir=/usr/local/lib threading=multi variant=release link=shared runtime-link=shared toolset=gcc install 
            這里之所以指定libdir是因?yàn)槟J(rèn)bjam會(huì)將庫(kù)文件安裝到/lib/下邊,不知道是不是個(gè)bug。好處是只需要指定一個(gè)庫(kù)的編譯,bjam就可以在install的時(shí)間將所有的頭文件準(zhǔn)備就緒了。
            查看一下:
            ls -l /usr/local/include/boost-1_39/boost/python

            文件已經(jīng)在了,再次回到cmake的臨時(shí)目錄:

            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環(huán)境準(zhǔn)備妥當(dāng)了,下一步體驗(yàn)一下其Helloworld。

             

            • 初試Boost.Python<CMake項(xiàng)目>

            新建一個(gè)目錄,并用CMake搭建項(xiàng)目環(huán)境:

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

            這里的boost.python作為一個(gè)根目錄,build目錄用于編譯和測(cè)試,CMakeLists.txt用于組織各個(gè)子項(xiàng)目,剩下的就是每個(gè)項(xiàng)目一個(gè)子目錄了,起步的這個(gè)就是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版本的庫(kù)的,因?yàn)閏make 2.6.4并不能很好的找到,默認(rèn)總是找到1.38的,如果沒有安裝多個(gè)版本的boost,可能沒有這么麻煩。接下來(lái)就是把HelloWorld那個(gè)子目錄包進(jìn)來(lái)。

            cd HelloWorld
            cat CMakeLists.txt
            具體內(nèi)容如下(這里將默認(rèn)CMake生成的動(dòng)態(tài)庫(kù)的lib前綴去掉,因?yàn)閜ython不喜歡這個(gè),:-)):
            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,將測(cè)試代碼拿進(jìn)來(lái)
            #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
            查看生成的庫(kù)文件:
            cd lib
            ls -lh hello.so
            file hello.so

            接下來(lái)用測(cè)試一番,啟動(dòng)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()
            

            這里嘗試的幾個(gè)方法都已經(jīng)湊效:構(gòu)造、析構(gòu)、greet/set,剛好就是前邊expose的那些了:

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

             

            下一步再嘗試一些復(fù)雜的東東。

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


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            <2025年6月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            亚洲国产精品无码久久一线| 婷婷久久综合九色综合98| 久久久综合九色合综国产| 无码国内精品久久人妻| 国产精品久久久久影院嫩草| 99久久国产主播综合精品| 久久99精品久久久久久噜噜| 久久男人中文字幕资源站| 人妻无码久久一区二区三区免费| 久久ZYZ资源站无码中文动漫| 四虎久久影院| 99久久精品国产高清一区二区 | 国产精品亚洲美女久久久| 国产欧美久久久精品影院| 99re这里只有精品热久久| 欧美大战日韩91综合一区婷婷久久青草 | 亚洲精品tv久久久久久久久久| 丰满少妇人妻久久久久久 | 国产亚洲欧美成人久久片| 国产成人精品久久| 久久久久亚洲?V成人无码| 9久久9久久精品| 久久久久久久久66精品片| 国产午夜精品久久久久九九| 97精品国产97久久久久久免费| 国产成人精品久久| 久久久久亚洲AV片无码下载蜜桃| 久久综合给合综合久久| 久久婷婷综合中文字幕| 99精品久久久久中文字幕| 热久久最新网站获取| 久久久久亚洲AV无码专区桃色 | 四虎亚洲国产成人久久精品| 久久国产精品久久久| 久久夜色精品国产噜噜噜亚洲AV| 亚洲色欲久久久久综合网| 久久精品国产黑森林| 久久精品夜色噜噜亚洲A∨ | 久久99热国产这有精品| 狠狠色丁香久久婷婷综合五月| 亚洲香蕉网久久综合影视|