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

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 3.3 檢測Python模塊和包 **NOTE**:*此示例代碼可以在 https://github.com/devcafe/cmake-cookbook/tree/v1.0/chapter-03/recipe-03 中找到,包含一個C++示例。該示例在CMake 3.5版(或更高版本)中是有效的,并且已經在GNU/Linux、macOS和Windows上進行過測試。* 前面的示例中,我們演示了如何檢測Python解釋器,以及如何編譯一個簡單的C程序(嵌入Python解釋器)。通常,代碼將依賴于特定的Python模塊,無論是Python工具、嵌入Python的程序,還是擴展Python的庫。例如,科學界非常流行使用NumPy處理矩陣問題。依賴于Python模塊或包的項目中,確定滿足對這些Python模塊的依賴非常重要。本示例將展示如何探測用戶的環境,以找到特定的Python模塊和包。 ## 準備工作 我們將嘗試在C++程序中嵌入一個稍微復雜一點的例子。這個示例再次引用[Python在線文檔](https://docs.python.org/3.5/extending/embedding.html#pureembedded),并展示了如何通過調用編譯后的C++可執行文件,來執行用戶定義的Python模塊中的函數。 Python 3示例代碼(`Py3-pure-embedding.cpp`)包含以下源代碼(請參見https://docs.python.org/2/extending/embedding.html#pure-embedded 與Python 2代碼等效): ```c++ #include <Python.h> int main(int argc, char* argv[]) { PyObject* pName, * pModule, * pDict, * pFunc; PyObject* pArgs, * pValue; int i; if (argc < 3) { fprintf(stderr, "Usage: pure-embedding pythonfile funcname [args]\n"); return 1; } Py_Initialize(); PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append(\".\")"); pName = PyUnicode_DecodeFSDefault(argv[1]); /* Error checking of pName left out */ pModule = PyImport_Import(pName); Py_DECREF(pName); if (pModule != NULL) { pFunc = PyObject_GetAttrString(pModule, argv[2]); /* pFunc is a new reference */ if (pFunc && PyCallable_Check(pFunc)) { pArgs = PyTuple_New(argc - 3); for (i = 0; i < argc - 3; ++i) { pValue = PyLong_FromLong(atoi(argv[i + 3])); if (!pValue) { Py_DECREF(pArgs); Py_DECREF(pModule); fprintf(stderr, "Cannot convert argument\n"); return 1; } /* pValue reference stolen here: */ PyTuple_SetItem(pArgs, i, pValue); } pValue = PyObject_CallObject(pFunc, pArgs); Py_DECREF(pArgs); if (pValue != NULL) { printf("Result of call: %ld\n", PyLong_AsLong(pValue)); Py_DECREF(pValue); } else { Py_DECREF(pFunc); Py_DECREF(pModule); PyErr_Print(); fprintf(stderr, "Call failed\n"); return 1; } } else { if (PyErr_Occurred()) PyErr_Print(); fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]); } Py_XDECREF(pFunc); Py_DECREF(pModule); } else { PyErr_Print(); fprintf(stderr, "Failed to load \"%s\"\n", argv[1]); return 1; } Py_Finalize(); return 0; } ``` 我們希望嵌入的Python代碼(`use_numpy.py`)使用NumPy設置一個矩陣,所有矩陣元素都為1.0: ```python import numpy as np def print_ones(rows, cols): A = np.ones(shape=(rows, cols), dtype=float) print(A) # we return the number of elements to verify # that the C++ code is able to receive return values num_elements = rows*cols return(num_elements) ``` ## 具體實施 下面的代碼中,我們能夠使用CMake檢查NumPy是否可用。我們需要確保Python解釋器、頭文件和庫在系統上是可用的。然后,將再來確認NumPy的可用性: 1. 首先,我們定義了最低CMake版本、項目名稱、語言和C++標準: ```cmake cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(recipe-03 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) ``` 2. 查找解釋器、頭文件和庫的方法與前面的方法完全相同: ```cmake find_package(PythonInterp REQUIRED) find_package(PythonLibs ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} EXACT REQUIRED) ``` 3. 正確打包的Python模塊,指定安裝位置和版本。可以在`CMakeLists.txt`中執行Python腳本進行探測: ```cmake execute_process( COMMAND ${PYTHON_EXECUTABLE} "-c" "import re, numpy; print(re.compile('/__init__.py.*').sub('',numpy.__file__))" RESULT_VARIABLE _numpy_status OUTPUT_VARIABLE _numpy_location ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) ``` 4. 如果找到NumPy,則`_numpy_status`變量為整數,否則為錯誤的字符串,而`_numpy_location`將包含NumPy模塊的路徑。如果找到NumPy,則將它的位置保存到一個名為`NumPy`的新變量中。注意,新變量被緩存,這意味著CMake創建了一個持久性變量,用戶稍后可以修改該變量: ```cmake if(NOT _numpy_status) set(NumPy ${_numpy_location} CACHE STRING "Location of NumPy") endif() ``` 5. 下一步是檢查模塊的版本。同樣,我們在`CMakeLists.txt`中施加了一些Python魔法,將版本保存到`_numpy_version`變量中: ```cmake execute_process( COMMAND ${PYTHON_EXECUTABLE} "-c" "import numpy; print(numpy.__version__)" OUTPUT_VARIABLE _numpy_version ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) ``` 6. 最后,`FindPackageHandleStandardArgs`的CMake包以正確的格式設置`NumPy_FOUND`變量和輸出信息: ```cmake include(FindPackageHandleStandardArgs) find_package_handle_standard_args(NumPy FOUND_VAR NumPy_FOUND REQUIRED_VARS NumPy VERSION_VAR _numpy_version ) ``` 7. 一旦正確的找到所有依賴項,我們就可以編譯可執行文件,并將其鏈接到Python庫: ```cmake add_executable(pure-embedding "") target_sources(pure-embedding PRIVATE Py${PYTHON_VERSION_MAJOR}-pure-embedding.cpp ) target_include_directories(pure-embedding PRIVATE ${PYTHON_INCLUDE_DIRS} ) target_link_libraries(pure-embedding PRIVATE ${PYTHON_LIBRARIES} ) ``` 8. 我們還必須保證`use_numpy.py`在`build`目錄中可用: ```cmake add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/use_numpy.py COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/use_numpy.py ${CMAKE_CURRENT_BINARY_DIR}/use_numpy.py DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/use_numpy.py ) # make sure building pure-embedding triggers the above custom command target_sources(pure-embedding PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/use_numpy.py ) ``` 9. 現在,我們可以測試嵌入的代碼: ```shell $ mkdir -p build $ cd build $ cmake .. -- ... -- Found PythonInterp: /usr/bin/python (found version "3.6.5") -- Found PythonLibs: /usr/lib/libpython3.6m.so (found suitable exact version "3.6.5") -- Found NumPy: /usr/lib/python3.6/site-packages/numpy (found version "1.14.3") $ cmake --build . $ ./pure-embedding use_numpy print_ones 2 3 [[1. 1. 1.] [1. 1. 1.]] Result of call: 6 ``` ## 工作原理 例子中有三個新的CMake命令,需要`include(FindPackageHandleStandardArgs)`: * `execute_process` * `add_custom_command` * `find_package_handle_standard_args` `execute_process`將作為通過子進程執行一個或多個命令。最后,子進程返回值將保存到變量作為參數,傳遞給`RESULT_VARIABLE`,而管道標準輸出和標準錯誤的內容將被保存到變量作為參數傳遞給`OUTPUT_VARIABLE`和`ERROR_VARIABLE`。`execute_process`可以執行任何操作,并使用它們的結果來推斷系統配置。本例中,用它來確保NumPy可用,然后獲得模塊版本。 `find_package_handle_standard_args`提供了,用于處理與查找相關程序和庫的標準工具。引用此命令時,可以正確的處理與版本相關的選項(`REQUIRED`和`EXACT`),而無需更多的CMake代碼。稍后將介紹`QUIET`和`COMPONENTS`選項。本示例中,使用了以下方法: ```cmake include(FindPackageHandleStandardArgs) find_package_handle_standard_args(NumPy FOUND_VAR NumPy_FOUND REQUIRED_VARS NumPy VERSION_VAR _numpy_version ) ``` 所有必需的變量都設置為有效的文件路徑(NumPy)后,發送到模塊(`NumPy_FOUND`)。它還將版本保存在可傳遞的版本變量(`_numpy_version`)中并打印: ```shell -- Found NumPy: /usr/lib/python3.6/site-packages/numpy (found version "1.14.3") ``` 目前的示例中,沒有進一步使用這些變量。如果返回`NumPy_FOUND`為`FALSE`,則停止配置。 最后,將`use_numpy.py`復制到`build`目錄,對代碼進行注釋: ```cmake add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/use_numpy.py COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/use_numpy.py ${CMAKE_CURRENT_BINARY_DIR}/use_numpy.py DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/use_numpy.py ) target_sources(pure-embedding PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/use_numpy.py ) ``` 我們也可以使用`file(COPY…)`命令來實現復制。這里,我們選擇使用`add_custom_command`,來確保文件在每次更改時都會被復制,而不僅僅是第一次運行配置時。我們將在第5章更詳細地討論`add_custom_command`。還要注意`target_sources`命令,它將依賴項添加到`${CMAKE_CURRENT_BINARY_DIR}/use_numpy.py`;這樣做是為了確保構建目標,能夠觸發之前的命令。
                  <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>

                              哎呀哎呀视频在线观看