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

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 9.3 使用Cython構建C++和Python項目 **NOTE**:*此示例代碼可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-9/recipe-03 中找到,其中有一個C++示例。該示例在CMake 3.5版(或更高版本)中是有效的,并且已經在GNU/Linux、macOS和Windows上進行過測試。* Cython是一個靜態編譯器,它允許為Python編寫C擴展。Cython是一個非常強大的工具,使用Cython編程語言(基于Pyrex)。Cython的一個典型用例是加快Python代碼的速度,它也可以用于通過Cython層使Python與C(++)接口對接。本示例中,我們將重點介紹后一種用例,并演示如何在CMake的幫助下使用Cython與C(++)和Python進行對接。 ## 準備工作 我們將使用以下C++代碼(`account.cpp`): ```c++ #include "account.hpp" Account::Account() : balance(0.0) {} Account::~Account() {} void Account::deposit(const double amount) { balance += amount; } void Account::withdraw(const double amount) { balance -= amount; } double Account::get_balance() const { return balance; } ``` 代碼提供了以下接口(`account.hpp`): ```c++ #pragma once class Account { public: Account(); ~Account(); void deposit(const double amount); void withdraw(const double amount); double get_balance() const; private: double balance; }; ``` 使用這個示例代碼,我們可以創建余額為零的銀行帳戶。可以在帳戶上存款和取款,還可以使用`get_balance()`查詢帳戶余額。余額本身是`Account`類的私有成員。 我們的目標是能夠直接從Python與這個C++類進行交互。換句話說,在Python方面,我們希望能夠做到這一點: ```python account = Account() account.deposit(100.0) account.withdraw(50.0) balance = account.get_balance() ``` 為此,需要一個Cython接口文件(調用`account.pyx`): ```python # describe the c++ interface cdef extern from "account.hpp": cdef cppclass Account: Account() except + void deposit(double) void withdraw(double) double get_balance() # describe the python interface cdef class pyAccount: cdef Account *thisptr def __cinit__(self): self.thisptr = new Account() def __dealloc__(self): del self.thisptr def deposit(self, amount): self.thisptr.deposit(amount) def withdraw(self, amount): self.thisptr.withdraw(amount) def get_balance(self): return self.thisptr.get_balance() ``` ## 具體實施 如何生成Python接口: 1. `CMakeLists.txt`定義CMake依賴項、項目名稱和語言: ```cmake # define minimum cmake version cmake_minimum_required(VERSION 3.5 FATAL_ERROR) # project name and supported language project(recipe-03 LANGUAGES CXX) # require C++11 set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) ``` 2. Windows上,最好不要保留未定義的構建類型,這樣我們就可以將該項目的構建類型與Python環境的構建類型相匹配。這里我們默認為Release類型: ```cmake if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) endif() ``` 3. 在示例中,還需要Python解釋器: ```cmake find_package(PythonInterp REQUIRED) ``` 4. 下面的CMake代碼將構建Python模塊: ```cmake # directory cointaining UseCython.cmake and FindCython.cmake list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake-cython) # this defines cython_add_module include(UseCython) # tells UseCython to compile this file as a c++ file set_source_files_properties(account.pyx PROPERTIES CYTHON_IS_CXX TRUE) # create python module cython_add_module(account account.pyx account.cpp) # location of account.hpp target_include_directories(account PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) ``` 5. 定義一個測試: ```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 ) ``` 6. `python_test`執行`test.py`,這里進行一些存款和取款操作,并驗證余額: ```cmake import os import sys sys.path.append(os.getenv('ACCOUNT_MODULE_PATH')) from account import pyAccount as 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 ``` 7. 有了這個,我們就可以配置、構建和測試代碼了: ```shell $ mkdir -p build $ cd build $ cmake .. $ cmake --build . $ ctest Start 1: python_test 1/1 Test #1: python_test ...................... Passed 0.03 sec 100% tests passed, 0 tests failed out of 1 Total Test time (real) = 0.03 sec ``` ## 工作原理 本示例中,使用一個相對簡單的`CMakeLists.txt`文件對接了Python和C++,但是是通過使用`FindCython.cmake`進行的實現。`UseCython.cmake`模塊,放置在`cmake-cython`下。這些模塊包括使用以下代碼: ```cmake # directory contains UseCython.cmake and FindCython.cmake list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake-cython) # this defines cython_add_module include(UseCython) ``` `FindCython.cmake`包含在`UseCython.cmake`中,并定義了`${CYTHON_EXECUTABLE}`變量。后一個模塊定義了`cython_add_module`和`cython_add_standalone_executable`函數,它們分別用于創建Python模塊和獨立的可執行程序。這兩個模塊都可從 https://github.com/thewtex/cython-cmake-example/tree/master/cmake 下載。 這個示例中,使用`cython_add_module`創建一個Python模塊庫。注意,將使用非標準的`CYTHON_IS_CXX`源文件屬性設置為`TRUE`,以便`cython_add_module`函數知道如何將`pyx`作為`C++`文件進行編譯: ```cmake # tells UseCython to compile this file as a c++ file set_source_files_properties(account.pyx PROPERTIES CYTHON_IS_CXX TRUE) # create python module cython_add_module(account account.pyx account.cpp) ``` Python模塊在`${CMAKE_CURRENT_BINARY_DIR}`中創建,為了讓Python的`test.py`腳本找到它,我們使用一個自定義環境變量傳遞相關的路徑,該環境變量用于在`test.py`中設置`path`變量。請注意,如何將命令設置為調用CMake可執行文件本身,以便在執行Python腳本之前設置本地環境。這為我們提供了平臺獨立性,并避免了環境污染: ```cmake 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 ) ``` 我們來看看`account.pyx`文件,這是Python與C++之間的接口文件,并對C++接口進行描述: ```python # describe the c++ interface cdef extern from "account.hpp": cdef cppclass Account: Account() except + void deposit(double) void withdraw(double) double get_balance() ``` 可以看到`cinit`構造函數、`__dealloc__`析構函數以及`deposit`和`withdraw`方法是如何與對應的C++實現相匹配的。 總之,發現了一種機制,通過引入對Cython模塊的依賴來耦合Python和C++。該模塊可以通過`pip`安裝到虛擬環境或Pipenv中,或者使用Anaconda來安裝。 ## 更多信息 C語言可以進行類似地耦合。如果希望利用構造函數和析構函數,我們可以在C接口之上封裝一個C++層。 類型化Memoryview提供了有趣的功能,可以映射和訪問由C/C++直接在Python中分配的內存,而不需要任何創建:http://cython.readthedocs.io/en/latest/src/userguide/memoryviews.html 。它們使得將NumPy數組直接映射為C++數組成為可能。
                  <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>

                              哎呀哎呀视频在线观看