可以使用 Python 工具来分析和操作程序的输出。然而,还有更强大的方法可以将解释语言(如 Python)与编译语言(如 C 或 C++)组合在一起使用。一种是扩展 Python,通过编译成共享库的 C 或 C++ 模块为 Python 提供新类型和新功能,这是第 9 章的主题;另一种是将 Python 解释器嵌入到 C 或 C++ 程序中。两种方法都需要满足一个前提:三个组件所使用的 Python 版本必须相同。我们已经演示了如何找到 Python 解释器;本示例将展示如何检测其余两个组件。
注意:本示例包含一个 C 示例,在 CMake 3.5 或更高版本中有效,并已在 GNU/Linux、macOS 和 Windows 上测试通过。
具体步骤
我们将一段简单的 Python 代码嵌入到 C 程序中,这段代码可以在 Python 文档中找到,源文件称为 hello-embedded-python.c:
#include <Python.h>
int main(int argc, char *argv[]) {
Py_SetProgramName(argv[0]); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print 'Today is',ctime(time())\n");
Py_Finalize();
return 0;
}
此代码将在程序中初始化 Python 解释器的实例,并使用 Python 的 time 模块打印日期。
FindPythonLibs.cmake 模块将查找 Python 头文件和库的标准位置。由于我们的项目需要这些依赖项,如果没有找到,将停止配置并报出错误。
注意,我们显式地要求 CMake 检测已安装的 Python 可执行文件,这是为了确保可执行文件、头文件和库都匹配同一个版本——版本不一致可能会在运行时导致崩溃。我们通过 FindPythonInterp.cmake 中定义的 PYTHON_VERSION_MAJOR 和 PYTHON_VERSION_MINOR 来实现:
find_package(PythonInterp REQUIRED)
find_package(PythonLibs ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} EXACT REQUIRED)
使用 EXACT 关键字,限制 CMake 检测特定的版本,在本例中就是匹配相应 Python 版本的头文件和库。还可以使用 PYTHON_VERSION_STRING 变量进行更精确的匹配:
find_package(PythonInterp REQUIRED)
find_package(PythonLibs ${PYTHON_VERSION_STRING} EXACT REQUIRED)
当 Python 不在标准安装目录中时,如何确定 Python 头文件和库的位置是正确的?可以通过 CLI 的 -D 选项传递 PYTHON_LIBRARY 和 PYTHON_INCLUDE_DIR 选项,强制 CMake 查找特定的目录,这样就能获得所需的 Python 版本。
提示:有时需要将
-D PYTHON_EXECUTABLE、-D PYTHON_LIBRARY和-D PYTHON_INCLUDE_DIR传递给 CMake CLI,以便找到并定位相应版本的组件。
更多信息
要将 Python 解释器及其开发组件匹配为完全相同的版本可能非常困难,对于将它们安装在非标准位置、或系统上安装了多个版本的情况尤其如此。CMake 3.12 版本中增加了新的 Python 检测模块,旨在解决这个棘手的问题。使用新模块后,CMakeLists.txt 的检测部分可以简化为:
find_package(Python COMPONENTS Interpreter Development REQUIRED)