<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 9.4 使用Boost.Python構建C++和Python項目 **NOTE**:*此示例代碼可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-9/recipe-04 中找到,其中有一個C++示例。該示例在CMake 3.5版(或更高版本)中是有效的,并且已經在GNU/Linux、macOS和Windows上進行過測試。* Boost庫為C++代碼提供了Python接口。本示例將展示如何在依賴于Boost的C++項目中使用CMake,之后將其作為Python模塊發布。我們將重用前面的示例,并嘗試用Cython示例中的C++實現(`account.cpp`)進行交互。 ## 準備工作 保持`account.cpp`不變的同時,修改前一個示例中的接口文件(`account.hpp`): ```c++ #pragma once #define BOOST_PYTHON_STATIC_LIB #include <boost/python.hpp> class Account { public: Account(); ~Account(); void deposit(const double amount); void withdraw(const double amount); double get_balance() const; private: double balance; }; namespace py = boost::python; BOOST_PYTHON_MODULE(account) { py::class_<Account>("Account") .def("deposit", &Account::deposit) .def("withdraw", &Account::withdraw) .def("get_balance", &Account::get_balance); } ``` ## 具體實施 如何在C++項目中使用Boost.Python的步驟: 1. 和之前一樣,首先定義最低版本、項目名稱、支持語言和默認構建類型: ```cmake # define minimum cmake version cmake_minimum_required(VERSION 3.5 FATAL_ERROR) # project name and supported language project(recipe-04 LANGUAGES CXX) # require C++11 set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) # we default to Release build type if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) endif() ``` 2. 本示例中,依賴Python和Boost庫,以及使用Python進行測試。Boost.Python組件依賴于Boost版本和Python版本,因此需要對這兩個組件的名稱進行檢測: ```cmake # for testing we will need the python interpreter find_package(PythonInterp REQUIRED) # we require python development headers find_package(PythonLibs ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} EXACT REQUIRED) # now search for the boost component # depending on the boost version it is called either python, # python2, python27, python3, python36, python37, ... list( APPEND _components python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR} python${PYTHON_VERSION_MAJOR} python ) set(_boost_component_found "") foreach(_component IN ITEMS ${_components}) find_package(Boost COMPONENTS ${_component}) if(Boost_FOUND) set(_boost_component_found ${_component}) break() endif() endforeach() if(_boost_component_found STREQUAL "") message(FATAL_ERROR "No matching Boost.Python component found") endif() ``` 3. 使用以下命令,定義Python模塊及其依賴項: ```cmake # create python module add_library(account MODULE account.cpp ) target_link_libraries(account PUBLIC Boost::${_boost_component_found} ${PYTHON_LIBRARIES} ) target_include_directories(account PRIVATE ${PYTHON_INCLUDE_DIRS} ) # prevent cmake from creating a "lib" prefix set_target_properties(account PROPERTIES PREFIX "" ) if(WIN32) # python will not import dll but expects pyd set_target_properties(account PROPERTIES SUFFIX ".pyd" ) endif() ``` 4. 最后,定義了一個測試: ```cmake # turn on testing enable_testing() # define test add_test( NAME python_test COMMAND ${CMAKE_COMMAND} -E env ACCOUNT_MODULE_PATH=$<TARGET_FILE_DIR:account> ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test.py ) ``` 5. 配置、編譯和測試: ```shell $ mkdir -p build $ cd build $ cmake .. $ cmake --build . $ ctest Start 1: python_test 1/1 Test #1: python_test ...................... Passed 0.10 sec 100% tests passed, 0 tests failed out of 1 Total Test time (real) = 0.11 sec ``` ## 工作原理 現在,不依賴于Cython模塊,而是依賴于在系統上的Boost庫,以及Python的開發頭文件和庫。 Python的開發頭文件和庫的搜索方法如下: ```cmake find_package(PythonInterp REQUIRED) find_package(PythonLibs ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} EXACT REQUIRED) ``` 首先搜索解釋器,然后搜索開發頭和庫。此外,對`PythonLibs`的搜索要求開發頭文件和庫的主版本和次版本,與解釋器的完全相同。但是,命令組合不能保證找到完全匹配的版本。 定位Boost.Python時,我們試圖定位的組件的名稱既依賴于Boost版本,也依賴于我們的Python環境。根據Boost版本的不同,可以調用python、python2、python3、python27、python36、python37等等。我們從特定的名稱搜索到更通用的名稱,已經解決了這個問題,只有在沒有找到匹配的名稱時才會失敗: ```cmake list( APPEND _components python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR} python${PYTHON_VERSION_MAJOR} python ) set(_boost_component_found "") foreach(_component IN ITEMS ${_components}) find_package(Boost COMPONENTS ${_component}) if(Boost_FOUND) set(_boost_component_found ${_component}) break() endif() endforeach() if(_boost_component_found STREQUAL "") message(FATAL_ERROR "No matching Boost.Python component found") endif() ``` 可以通過設置額外的CMake變量,來調整Boost庫的使用方式。例如,CMake提供了以下選項: * **Boost_USE_STATIC_LIBS**:設置為ON之后,可以使用靜態版本的Boost庫。 * **Boost_USE_MULTITHREADED**:設置為ON之后,可以切換成多線程版本。 * **Boost_USE_STATIC_RUNTIME**:設置為ON之后,可以在C++運行時靜態的連接不同版本的Boost庫。 此示例的另一個特點是使用`add_library`的模塊選項。我們已經從第1章第3節了解到,CMake接受以下選項作為`add_library`的第二個有效參數: * **STATIC**:創建靜態庫,也就是對象文件的存檔,用于鏈接其他目標時使用,例如:可執行文件 * **SHARED**:創建共享庫,也就是可以動態鏈接并在運行時加載的庫 * **OBJECT**:創建對象庫,也就是對象文件不需要將它們歸檔到靜態庫中,也不需要將它們鏈接到共享對象中 `MODULE`選項將生成一個插件庫,也就是動態共享對象(DSO),沒有動態鏈接到任何可執行文件,但是仍然可以在運行時加載。由于我們使用C++來擴展Python,所以Python解釋器需要能夠在運行時加載我們的庫。使用`MODULE`選項進行`add_library`,可以避免系統在庫名前添加前綴(例如:Unix系統上的lib)。后一項操作是通過設置適當的目標屬性來執行的,如下所示: ```cmake set_target_properties(account PROPERTIES PREFIX "" ) ``` 完成Python和C++接口的示例,需要向Python代碼描述如何連接到C++層,并列出對Python可見的符號,我們也有可能重新命名這些符號。在上一個示例中,我們在另一個單獨的` account.pyx`文件這樣用過。當使用Boost.Python時,我們直接用C++代碼描述接口,理想情況下接近期望的接口類或函數定義: ```c++ BOOST_PYTHON_MODULE(account) { py::class_<Account>("Account") .def("deposit", &Account::deposit) .def("withdraw", &Account::withdraw) .def("get_balance", &Account::get_balance); } ``` `BOOST_PYTHON_MODULE`模板包含在`<boost/python>`中,負責創建Python接口。該模塊將公開一個`Account` Python類,該類映射到C++類。這種情況下,我們不需要顯式地聲明構造函數和析構函數——編譯器會有默認實現,并在創建Python對象時自動調用: ```c++ myaccount = Account() ``` 當對象超出范圍并被回收時,將調用析構函數。另外,觀察`BOOST_PYTHON_MODULE`如何聲明`deposit`、`withdraw`和`get_balance`函數,并將它們映射為相應的C++類方法。 這樣,Python可以在`PYTHONPATH`中找到編譯后的模塊。這個示例中,我們實現了Python和C++層之間相對干凈的分離。Python代碼的功能不受限制,不需要類型注釋或重寫名稱,并保持Python風格: ```python from account import Account account1 = Account() account1.deposit(100.0) account1.deposit(100.0) account2 = Account() account2.deposit(200.0) account2.deposit(200.0) account1.withdraw(50.0) assert account1.get_balance() == 150.0 assert account2.get_balance() == 400.0 ``` ## 更多信息 這個示例中,我們依賴于系統上安裝的Boost,因此CMake代碼會嘗試檢測相應的庫。或者,可以將Boost源與項目一起提供,并將此依賴項,作為項目的一部分構建。Boost使用的是一種可移植的方式將Python與C(++)進行連接。然而,與編譯器支持和C++標準相關的可移植性是有代價的,因為Boost.Python不是輕量級依賴項。在接下來的示例中,我們將討論Boost.Python的輕量級替代方案。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看