在本文中,你将为 CPython 生成一个C++扩展模块,以计算双曲正切值并从 Python 代码调用它。 该例程首先在 Python 中实现,以演示在 C++ 中实现相同例程的相对性能提升。
以 C++(或 C) 编写的代码模块通常用于扩展 Python 解释器的功能。 有三种主要类型的扩展模块:
- 加速器模块:启用加速性能。 由于 Python 是一种解释语言,因此可以在 C++ 中编写加速器模块以提高性能。
- 包装器模块:向 Python 代码公开现有的 C/C++ 接口,或公开更符合 Python 风格的 API,使其更易于 Python 使用。
-
低级别系统访问模块:创建系统访问模块以达到运行时、作系统或基础硬件的
CPython
较低级别功能。
本文演示了两种使 C++ 扩展模块可供 Python 使用的方法:
- 如 Python 文档中所述,请使用标准
CPython
扩展。 - 使用 PyBind11,建议使用 C++11,因为其简单性。 若要确保兼容性,请确保使用最新版本的 Python 之一。
本演练的完整示例在 GitHub 上提供了 python-samples-vs-cpp-extension。
先决条件
安装了 Python 开发工作负载的 Visual Studio 2017 或更高版本。 该工作负载包括 Python 本机开发工具,这些工具添加本机扩展所需的C++工作负载和工具集。
有关安装选项的详细信息,请参阅 安装对 Visual Studio 的 Python 支持。
注释
安装 数据科学和分析应用程序 工作负荷时,默认情况下会安装 Python 和 Python 本机开发工具 选项。
如果单独安装 Python,请确保在 Python 安装程序中的“高级选项”下选择“下载调试符号”。 要在 Python 代码和本机代码之间进行混合模式调试,需要启用此选项。
创建 Python 应用程序
按照以下步骤创建 Python 应用程序。
通过选择“文件>新建>项目”在 Visual Studio 中创建新的 Python项目。
在“ 创建新项目 ”对话框中,搜索 python。 选择 Python 应用程序 模板,然后选择“ 下一步”。
输入项目名称和位置,然后选择“创建”。
Visual Studio 将创建新项目。 项目在 解决方案资源管理器 中打开,项目文件(.py)将在代码编辑器中打开。
在 .py 文件中,粘贴以下代码。 若要体验某些 Python 编辑功能,请尝试手动输入代码。
这段代码在不使用数学库的情况下计算双曲正切,之后将通过 Python 原生扩展对其进行加速。
小窍门
在C++中重写代码之前,请在纯 Python 中编写代码。 这样,可以更轻松地检查以确保本机 Python 代码正确无误。
from random import random from time import perf_counter # Change the value of COUNT according to the speed of your computer. # The value should enable the benchmark to complete in approximately 2 seconds. COUNT = 500000 DATA = [(random() - 0.5) * 3 for _ in range(COUNT)] e = 2.7182818284590452353602874713527 def sinh(x): return (1 - (e ** (-2 * x))) / (2 * (e ** -x)) def cosh(x): return (1 + (e ** (-2 * x))) / (2 * (e ** -x)) def tanh(x): tanh_x = sinh(x) / cosh(x) return tanh_x def test(fn, name): start = perf_counter() result = fn(DATA) duration = perf_counter() - start print('{} took {:.3f} seconds\n\n'.format(name, duration)) for d in result: assert -1 <= d <= 1, " incorrect values" if __name__ == "__main__": print('Running benchmarks with COUNT = {}'.format(COUNT)) test(lambda d: [tanh(x) for x in d], '[tanh(x) for x in d] (Python implementation)')
通过选择 调试>无调试开始 或使用键盘快捷键 Ctrl+F5 来运行程序。
此时会打开一个命令窗口以显示程序输出。
在输出中,请注意基准进程报告的时间量。
在本演练中,基准过程大约需要 2 秒。
根据需要,调整代码中的变量值
COUNT
,使基准测试在大约 2 秒内在计算机上完成。再次运行程序,确认修改
COUNT
后的值在大约 2 秒内生成基准。
小窍门
运行基准测试时,请始终使用 “调试>开始”选项而不使用调试 选项。 此方法有助于避免在 Visual Studio 调试器中运行代码时产生的开销。
创建核心C++项目
按照以下步骤创建两个相同的C++项目: superfastcode 和 superfastcode2。 稍后,在每个项目中使用不同的方法向 Python 公开C++代码。
在 解决方案资源管理器中,右键单击解决方案名称,然后选择“ 添加新>项目”。
Visual Studio 解决方案可以同时包含 Python 和C++项目,这是使用 Visual Studio 进行 Python 开发的优点之一。
在“添加新项目”对话框中,将语言筛选器设置为C++,并在“搜索”框中输入空。
在项目模板结果列表中,选择 “空项目”,然后选择“ 下一步”。
在 “配置新项目 ”对话框中,输入 项目名称:
- 对于第一个项目,请输入名称 superfastcode。
- 对于第二个项目,请输入名称 superfastcode2。
选择 创建。
请务必重复这些步骤并创建两个项目。
小窍门
在 Visual Studio 中安装了 Python 本机开发工具时,可以使用替代方法。 可以从 Python 扩展模块 模板开始,该模板预先完成了本文中所述的许多步骤。
对于本文中的演练,从空项目开始,有助于逐步演示如何生成扩展模块。 了解该过程后,可以使用备用模板在编写自己的扩展时节省时间。
将C++文件添加到项目
接下来,将C++文件添加到每个项目。
在 解决方案资源管理器中,展开项目,右键单击 “源文件 ”节点,然后选择“ 添加新>项”。
在文件模板列表中,选择“C++文件”(.cpp)。
输入文件的名称作为module.cpp,然后选择“添加”。
重要
请确保文件名包含 .cpp 扩展名。 Visual Studio 查找扩展名 为.cpp 的文件,以便显示C++项目属性页。
在工具栏上,展开 “配置 ”下拉菜单并选择目标配置类型:
- 对于 64 位 Python 运行时,请激活 x64 配置。
- 对于 32 位 Python 运行时,请激活 Win32 配置。
请务必对两个项目重复这些步骤。
配置项目属性
将代码添加到新的C++文件之前,请配置每个C++模块项目的属性,并测试配置以确保一切正常。
需要为每个模块的 调试 和 发布 生成配置设置项目属性。
在 解决方案资源管理器中,右键单击C++模块项目(superfastcode 或 superfastcode2),然后选择“ 属性”。
为模块的 调试 版本配置属性,然后为 发布 版本配置相同的属性:
在“项目 属性页 ”对话框顶部,配置以下文件配置选项:
对于 配置,请选择 “调试 ”或“ 发布”。 你可能会看到这些带有 活动 前缀的选项。
对于 平台,请选择 “活动”(x64) 或 “活动”(Win32),具体取决于上一步中的选择。
注释
创建自己的项目时,需要根据特定的方案要求单独配置 调试 和 发布 配置。 在本练习中,将配置设置为使用 CPython 的发布版本。 此配置禁用C++运行时的某些调试功能,包括断言。 使用 CPython 调试二进制文件(python_d.exe)需要不同的设置。
设置下表中所述的其他项目属性。
若要更改属性值,请在属性字段中输入值。 对于某些字段,可以选择当前值以展开选项下拉菜单或打开对话框来帮助定义值。
更新选项卡上的值后,请在切换到其他选项卡之前选择 “应用 ”。此作有助于确保更改保持不变。
选项卡和分区 资产 价值 配置属性>常规 目标名称 指定模块的名称,以便在 Python 语句中(如 from...import
中的 superfastcode)引用。 定义 Python 模块时,请在C++代码中使用此同名。 若要使用项目的名称作为模块名称,请保留默认值 $<ProjectName>。 请在python_d.exe
名称末尾添加_d
。配置类型 动态库 (.dll) 配置属性>高级 目标文件扩展名 .pyd (Python 扩展模块) C/C++>常规 其他包含目录 根据安装情况添加 Python include 文件夹(例如 c:\Python36\include)。 C/C++>预处理 预处理器定义 如果存在,请将 _DEBUG 值更改为 NDEBUG 以匹配 CPython 的非debug 版本。 使用 python_d.exe时,请保留此值不变。 C/C++>代码生成 运行时库 多线程 DLL (/MD) 与 CPython 的发布(非调试)版本匹配。 使用 python_d.exe时,请将此值保留为多线程调试 DLL (/MDd)。 基本运行时检查 默认 链接器>常规 其他库目录 根据安装情况添加包含 .lib 文件的 Python libs 文件夹(例如 c:\Python36\libs)。 请务必指向包含 .lib 文件的 libs 文件夹,而不是包含.py文件的 Lib 文件夹。 重要
如果 C/C++ 选项卡未显示为项目属性的选项,则项目不包含 Visual Studio 标识为 C/C++ 源文件的代码文件。 如果在没有 .c 或 .cpp 文件扩展名的情况下创建源文件,则可能会出现这种情况。
如果在创建C++文件时意外输入 了 module.coo 而不是 module.cpp,Visual Studio 会创建该文件,但不会将文件类型设置为 C/C+ 编译器。 此文件类型是激活项目属性对话框中 C/C++ 属性选项卡的存在所必需的。 即使将代码文件重命名为 .cpp 文件扩展名,误识别仍然存在。
若要正确设置代码文件类型,请在 解决方案资源管理器中右键单击代码文件并选择“ 属性”。 对于 项类型,请选择 C/C++ 编译器。
更新所有属性后,选择“ 确定”。
对其他生成配置重复相同的步骤。
测试当前配置。 对两个C++项目的 调试 和 发布 版本重复以下步骤。
添加代码和测试配置
现在,你已准备好将代码添加到C++文件并测试 发布 版本。
对于 superfastcode C++ 项目,请在代码编辑器中打开 module.cpp 文件。
在 module.cpp 文件中,粘贴以下代码:
#include <Windows.h> #include <cmath> const double e = 2.7182818284590452353602874713527; double sinh_impl(double x) { return (1 - pow(e, (-2 * x))) / (2 * pow(e, -x)); } double cosh_impl(double x) { return (1 + pow(e, (-2 * x))) / (2 * pow(e, -x)); } double tanh_impl(double x) { return sinh_impl(x) / cosh_impl(x); }
保存更改。
生成C++项目的 发布 配置,以确认代码正确。
重复这些步骤,将代码添加到 superfastcode2 项目的 C++ 文件中,并测试 发布 版本。
将C++项目转换为 Python 扩展
若要使 C++ DLL 成为 Python 的扩展,请先修改导出的方法以与 Python 类型交互。 然后,添加一个函数来导出模块,以及模块方法的定义。
以下部分演示如何使用 CPython 扩展和 PyBind11 创建扩展。 superfasctcode 项目使用 CPython 扩展,superfasctcode2 项目实现 PyBind11。
使用 CPython 扩展
有关本节中介绍的代码的详细信息,请参阅 Python/C API 参考手册,尤其是 “模块对象 ”页。 查看参考内容时,请务必在右上角的下拉列表中选择 Python 版本。
对于 superfastcode C++ 项目,请在代码编辑器中打开 module.cpp 文件。
在 module.cpp 文件的顶部添加语句以包含 Python.h 头文件:
#include <Python.h>
将
tanh_impl
方法代码替换为能够接受和返回 Python 类型(即PyObject*
)的代码。PyObject* tanh_impl(PyObject* /* unused module reference */, PyObject* o) { double x = PyFloat_AsDouble(o); double tanh_x = sinh_impl(x) / cosh_impl(x); return PyFloat_FromDouble(tanh_x); }
在文件末尾,添加一个结构以定义如何将 C++
tanh_impl
函数呈现给 Python:static PyMethodDef superfastcode_methods[] = { // The first property is the name exposed to Python, fast_tanh // The second is the C++ function with the implementation // METH_O means it takes a single PyObject argument { "fast_tanh", (PyCFunction)tanh_impl, METH_O, nullptr }, // Terminate the array with an object containing nulls { nullptr, nullptr, 0, nullptr } };
添加另一个结构,以定义如何在 Python 代码中引用模块,尤其是在使用
from...import
语句时。此代码中导入的名称应与 “配置属性>常规>目标名称”下的项目属性中的值匹配。
在如下示例中,由于
fast_tanh
在superfastcode_methods
中定义,"superfastcode"
名称表示您可以在Python中使用from superfastcode import fast_tanh
语句。 C++项目内部的文件名(如 module.cpp)是无关紧要的。static PyModuleDef superfastcode_module = { PyModuleDef_HEAD_INIT, "superfastcode", // Module name to use with Python import statements "Provides some functions, but faster", // Module description 0, superfastcode_methods // Structure that defines the methods of the module };
添加 Python 加载模块时调用的方法。 方法名称必须是
PyInit_<module-name>
,其中 <模块名称> 与C++项目的 “配置属性>常规>目标名称” 属性完全匹配。 也就是说,方法名称与项目生成的 .pyd 文件的文件名匹配。PyMODINIT_FUNC PyInit_superfastcode() { return PyModule_Create(&superfastcode_module); }
生成C++项目并验证代码。 如果遇到错误,请参阅 “排查编译错误” 部分。
使用 PyBind11
如果您完成了上一部分中 superfastcode 项目的步骤,您可能会注意到练习需要模板代码来创建用于 C++ CPython 扩展的模块结构。 在本练习中,你发现 PyBind11 简化了编码过程。 在C++头文件中使用宏来完成相同的结果,但代码要少得多。 但是,需要执行额外的步骤来确保 Visual Studio 可以找到 PyBind11 库并包含文件。 有关本节中的代码的详细信息,请参阅 PyBind11 基础知识。
安装 PyBind11
第一步是在项目配置中安装 PyBind11。 在本练习中,你将使用 “开发人员 PowerShell ”窗口。
打开 “工具>命令行>开发人员 PowerShell ”窗口。
在 开发人员 PowerShell 窗口中,使用 pip 命令
pip install pybind11
或py -m pip install pybind11
安装 PyBind11。Visual Studio 安装 PyBind11 及其依赖包。
将 PyBind11 路径添加到项目
安装 PyBind11 后,需要将 PyBind11 路径添加到项目的 “附加包含目录 ”属性。
在 开发人员 PowerShell 中,运行命令
python -m pybind11 --includes
或py -m pybind11 --includes
。该操作将打印出一个需添加到项目属性中的 PyBind11 路径列表。
突出显示窗口中的路径列表,然后在窗口工具栏上选择“ 复制 ”(双页)。
连接路径的列表将添加到剪贴板。
在 解决方案资源管理器中,右键单击 superfastcode2 项目,然后选择“ 属性”。
在“ 属性页 ”对话框顶部的 “配置 ”字段,选择“ 发布”。 (您可能会看到此选项带有 活动 前缀。)
在对话框中的 C/C++>General 选项卡中,展开 “其他包含目录 ”属性的下拉菜单,然后选择“ 编辑”。
在弹出对话框中,添加复制的路径列表:
对从 开发人员 PowerShell 窗口复制的串联列表中的每个路径重复这些步骤:
选择 “确定 ”退出弹出对话框。
在 “属性页 ”对话框顶部,将鼠标悬停在 “其他包含目录” 属性的值上,并确认 PyBind11 路径存在。
单击确定以应用属性更改。
更新module.cpp文件
最后一步是将 PyBind11 头文件和宏代码添加到项目C++文件。
对于 superfastcode2 C++项目,请在代码编辑器中打开 module.cpp 文件。
在 module.cpp 文件的顶部添加语句以包含 pybind11.h 头文件:
#include <pybind11/pybind11.h>
在 module.cpp 文件的末尾,添加宏的代码
PYBIND11_MODULE
以定义C++函数的入口点:namespace py = pybind11; PYBIND11_MODULE(superfastcode2, m) { m.def("fast_tanh2", &tanh_impl, R"pbdoc( Compute a hyperbolic tangent of a single argument expressed in radians. )pbdoc"); #ifdef VERSION_INFO m.attr("__version__") = VERSION_INFO; #else m.attr("__version__") = "dev"; #endif }
生成C++项目并验证代码。 如果遇到错误,请参阅下一部分, 排查编译错误。
排查编译错误
查看以下部分,了解可能导致C++模块生成失败的可能问题。
错误:找不到头文件
Visual Studio 返回错误消息 ,如 E1696:无法打开源文件“Python.h” 或 C1083:无法打开包含文件:“Python.h”:无此类文件或目录。
此错误表示编译器找不到项目所需的标头 (.h) 文件。
对于 superfastcode 项目,请验证 C/C++>General>Additional Include Directory 项目属性是否包含 Python 安装 包含 文件夹的路径。 查看 “配置项目属性”中的步骤。
对于 superfastcode2 项目,请验证同一项目属性是否包含 PyBind11 安装 包含 文件夹的路径。 查看 添加 PyBind 路径的步骤。
有关访问 Python 安装配置信息的详细信息,请参阅 Python 文档。
错误:找不到 Python 库
Visual Studio 返回一个错误,指示编译器找不到项目所需的库 (DLL) 文件。
- 对于C++项目(superfastcode 或 superfastcode2),请验证 链接器>常规>其他库目录 属性是否包含 Python 安装的 libs 文件夹的路径。 查看 “配置项目属性”中的步骤。
有关访问 Python 安装配置信息的详细信息,请参阅 Python 文档。
与目标体系结构相关的链接器错误
Visual Studio 报告与项目的目标体系结构配置相关的链接器错误,例如 x64 或 Win32。
- 对于C++项目(superfastcode 或 superfastcode2),请更改目标配置以匹配 Python 安装。 例如,如果C++项目目标配置为 Win32,但 Python 安装为 64 位,请将C++项目目标配置更改为 x64。
测试代码并比较结果
将 DLL 结构化为 Python 扩展后,可以从 Python 项目引用它们,导入模块并使用其方法。
使 DLL 可供 Python 使用
可以通过多种方式向 Python 提供 DLL。 以下是需要考虑的两个选项:
如果 Python 项目和C++项目位于同一解决方案中,则可以使用以下方法:
在 解决方案资源管理器中,右键单击 Python 项目中的 “引用 ”节点,然后选择“ 添加引用”。
请确保为 Python 项目执行此作,而不是针对C++项目执行此作。
在 “添加引用 ”对话框中,展开“ 项目 ”选项卡。
选中 superfastcode 和 superfastcode2 项目的复选框,然后选择“ 确定”。
另一种方法是在 Python 环境中安装C++扩展模块。 此方法使该模块可用于其他 Python 项目。 有关详细信息,请参阅 setuptools 项目文档。
完成以下步骤,在 Python 环境中安装 C++ 扩展模块:
在 解决方案资源管理器中,右键单击C++项目,然后选择“ 添加新>项”。
在文件模板列表中,选择“C++文件”(.cpp)。
输入文件的名称作为 setup.py,然后选择“添加”。
请务必使用 Python(.py)扩展名输入文件名。 尽管使用了C++文件模板,Visual Studio 仍会将该文件识别为 Python 代码。
Visual Studio 将在代码编辑器中打开新文件。
将以下代码粘贴到新文件中。 选择与扩展方法对应的代码版本:
CPython 扩展 (superfastcode 项目):
from setuptools import setup, Extension sfc_module = Extension('superfastcode', sources = ['module.cpp']) setup( name='superfastcode', version='1.0', description='Python Package with superfastcode C++ extension', ext_modules=[sfc_module] )
PyBind11 (superfastcode2 项目):
from setuptools import setup, Extension import pybind11 cpp_args = ['-std=c++11', '-stdlib=libc++', '-mmacosx-version-min=10.7'] sfc_module = Extension( 'superfastcode2', sources=['module.cpp'], include_dirs=[pybind11.get_include()], language='c++', extra_compile_args=cpp_args, ) setup( name='superfastcode2', version='1.0', description='Python package with superfastcode2 C++ extension (PyBind11)', ext_modules=[sfc_module], )
在C++项目中,创建名为 pyproject.toml 的第二个文件,并粘贴以下代码:
[build-system] requires = ["setuptools", "wheel", "pybind11"] build-backend = "setuptools.build_meta"
TOML (.toml) 文件对配置文件使用 Tom 的“明显、最小语言”格式。
若要生成扩展,请在代码窗口选项卡中右键单击 pyproject.toml 文件名,然后选择“ 复制完整路径”。
在使用该名称之前,请从路径中删除 pyproject.toml 名称。
在 解决方案资源管理器中,展开解决方案的 Python 环境 节点。
右键单击活动 Python 环境(以粗体显示),然后选择“ 管理 Python 包”。
此时会打开 “Python 环境” 窗格。
如果已安装必要的包,会看到它列在此窗格中。
- 在继续之前,请选择包名称旁边的 X 以卸载它。
在 Python 环境 窗格的搜索框中,粘贴复制的路径,并从路径末尾删除 pyproject.toml 文件名。
选择 Enter 可从复制路径的位置安装模块。
小窍门
如果安装因权限错误而失败,请将参数添加到
--user
命令末尾,然后重试安装。
从 Python 调用 DLL
将 DLL 提供给 Python 后,如前一部分所述,即可从 Python 调用 superfastcode.fast_tanh
和 superfastcode2.fast_tanh2
函数。 然后,可以将函数性能与 Python 实现进行比较。
按照以下步骤从 Python 调用扩展模块 DLL:
在代码编辑器中打开 Python 项目的 .py 文件。
在文件末尾,添加以下代码以调用从 DLL 导出的方法并显示其输出:
from superfastcode import fast_tanh test(lambda d: [fast_tanh(x) for x in d], '[fast_tanh(x) for x in d] (CPython C++ extension)') from superfastcode2 import fast_tanh2 test(lambda d: [fast_tanh2(x) for x in d], '[fast_tanh2(x) for x in d] (PyBind11 C++ extension)')
通过选择 “>开始执行(不调试)” 或使用键盘快捷方式 Ctrl+F5 来运行 Python 程序。
注释
如果 “无调试启动 ”命令不可用,请在 解决方案资源管理器中右键单击 Python 项目,然后选择“ 设置为启动项目”。
当程序执行时,请注意,C++例程的运行速度比 Python 实现快约 5 到 20 倍。
下面是典型程序输出的示例:
Running benchmarks with COUNT = 500000 [tanh(x) for x in d] (Python implementation) took 0.758 seconds [fast_tanh(x) for x in d] (CPython C++ extension) took 0.076 seconds [fast_tanh2(x) for x in d] (PyBind11 C++ extension) took 0.204 seconds
请尝试增加
COUNT
变量,以便更明显地显示时间差异。C++模块的 调试 版本也运行速度比 发布 版本慢,因为调试生成不太优化,并且包含各种错误检查。 请尝试在生成配置之间进行切换以进行比较,但请记住更新之前为发布配置设置的属性。
解决进程速度和开销问题
在输出中,你可能会注意到 PyBind11 扩展的速度不如 CPython 扩展快,尽管它应该比纯 Python 实现更快。 差异的主要原因是使用 METH_O标志。 此标志不支持多个参数、参数名称或关键字参数。 PyBind11 会生成稍微更复杂的代码,以便为调用方提供更类似于 Python 的接口。 由于测试代码调用函数 50万次,结果可能导致开销大幅增加。
可以通过将 for
循环移动到原生 Python 代码来进一步降低开销。 此方法涉及使用迭代器协议(或函数参数的 PyBind11 py::iterable
类型)来处理每个元素。 删除 Python 和 C++ 之间的重复转换是减少处理序列所需的时间的有效方法。
排查导入错误
如果在尝试导入模块时收到消息 ImportError
,可以通过以下方式之一解决它:
通过项目引用生成时,请确保C++项目属性与为 Python 项目激活的 Python 环境匹配。 确认Include(.h)和Library(DLL)文件使用的是相同的文件夹位置。
确保正确命名输出文件,例如 superfastcode.pyd。 不正确的名称或扩展名会阻止导入必要的文件。
如果使用 setup.py 文件安装模块,请确保在为 Python 项目激活的 Python 环境中运行
pip
该命令。 在 解决方案资源管理器中扩展项目的活动 Python 环境时,应会看到C++项目的条目,例如 superfastcode。
调试C++代码
Visual Studio 支持将 Python 和C++代码一起调试。 以下步骤演示 superfastcode C++ 项目的调试过程,不过 superfastcode2 项目的调试过程也是相同的。
在 解决方案资源管理器中,右键单击 Python 项目,然后选择“ 属性”。
在“ 属性 ”窗格中,选择 “调试 ”选项卡,然后选择 “调试>启用本机代码调试 ”选项。
小窍门
启用本机代码调试时,Python 输出窗口可能会在程序完成后立即关闭,而不会暂停并显示 “按任意键继续 提示”。 若要在启用本机代码调试后强制暂停和提示,请将
-i
参数添加到“调试”选项卡上的“运行>解释器参数”字段。此参数使 Python 解释器在代码运行后进入交互模式。 程序等待你选择 Ctrl+Z+Enter 关闭窗口。 另一种方法是在 Python 程序末尾添加import os
和os.system("pause")
语句。 此代码复制原始暂停提示。选择 “文件>保存 ”(或 Ctrl+S)保存属性更改。
在 Visual Studio 工具栏上,将 “生成 ”配置设置为 “调试”。
由于代码通常需要更长的时间才能在调试器中运行,因此可能需要将 Python 项目中的
COUNT
变量 .py 文件更改为小于默认值五倍的值。 例如,将其从 500000 更改为 100000。在C++代码中,在方法的第一行
tanh_impl
上设置断点。选择 “调试>开始调试 ”或使用键盘快捷方式 F5 来启动调试器。
调用断点代码时,调试器将停止。 如果断点未命中,请检查以确保配置设置为 “调试”,并且确保你已保存项目,因为启动调试器时不会自动保存。
在断点处,您可以逐步执行C++代码,检查变量等等。 有关这些功能的详细信息,请参阅调试 Python 和C++。
备用方法
可以通过各种方式创建 Python 扩展,如下表所述。 本文将讨论前两行 CPython
PyBind11
。
方法 | 旧式 | 代表用户 |
---|---|---|
CPython 的 C/C++ 扩展模块 |
1991 | 标准库 |
PyBind11 (建议用于C++) | 2015 | |
西松 (推荐用于 C) | 2007 | gevent、 kivy |
HPy | 2019 | |
mypyc | 2017 | |
ctype | 2003 | oscrypto |
cffi | 2013 | 加密, pypy |
SWIG | 1996 | crfsuite |
Boost.Python | 2002 | |
cppyy | 2017 |