Visual studio 2022 编译 python c c 扩展 - housekeeper-software/tech GitHub Wiki

何时需要c/C++扩展

当一个任务用python实现效率太低的时候,可以考虑用C++实现。numpy,pytorch,tensorflow底层都是c++编写的,然后用python进行高层接口封装

准备知识

安装Python,注意,不要安装比较新的版本,尤其是最新版,因为优化了GIL,导致vs不能调试。所以,我们安装3.9版本。
在安装时,记得选择 Debug 符号,这样才可以编译Debug版本,进而可以调试c/c++扩展。
安装 Visual studio Community 2022,记得安装:
C/C++
Python 开发,需勾选 Python 本机开发工具

建立工程

1.新建一个工程目录
2.通过 Python应用程序模板新建一个Python工程
3.在此解决方案中添加一个c++空项目。

配置 c++ 工程

假设工程名字为 testc
1.在解决方案中右键点击C++工程->属性
2.选择x64(if x64 platform):
  (1)配置属性->常规->目标文件名
     如果想要把testc作为私有模块,那么这里写入 _$(ProjectName)_d,前面的下划线表示私有模块,
     如果不是私有的模块,则不需要前面的下划线,后面的_d表示Debug,如果是Release则不需要_d
  (2) 目标类型: 动态库(.dll)
  (3) 配置属性->高级->目标文件扩展名: .pyd,这是Windows下的c++扩展,Linux下的就是so即可。pyd就是dll。
  (4) 配置属性->C/C++->附加包含目录,设置为Python安装目录的include,比如: D:\Users\zxm\Python\Python39\include
  (5) 配置属性->连接器->附加库目录,设置为Python安装目录的libs目录,比如: D:\Users\zxm\Python\Python39\libs
  (6) 配置属性->连接器->输入->附加依赖项,这个不用设置,vs自动根据情况添加python.lib之类的

配置Python工程

1.在解决方案中右键点击 python工程->属性
2.在[调试]中"启用本机代码调试",同时,在解释器参数中输入 -i ,表示进入python交互控制台
3.在解决方案中,为python工程添加引用,指向刚才的C++工程。编译c++的时候,最后的输出被指向到python工程的输出目录,比如 x64/Debug,同时
  vs会自动将x64/Debug添加到os.path中,这样python就可以找到这个扩展

编译c++模块

写代码:
#include <Python.h>
...

static PyMethodDef testc_functions[] = {
	{"CreateIoCompletionPort", completion_CreateIoCompletionPort,
	 METH_VARARGS, CreateIoCompletionPort_doc},
	{"GetQueuedCompletionStatus", completion_GetQueuedCompletionStatus,
	 METH_VARARGS, GetQueuedCompletionStatus_doc},
	{"PostQueuedCompletionStatus", completion_PostQueuedCompletionStatus,
	 METH_VARARGS, PostQueuedCompletionStatus_doc},
	{NULL}
};

static struct PyModuleDef testc_module = {
	PyModuleDef_HEAD_INIT,
	"_testc",
	NULL,
	-1,
	testc_functions,
	NULL,
	NULL,
	NULL,
	NULL
};

PyMODINIT_FUNC
PyInit__testc(void) {
 return PyModule_Create(&testc_module);
}

这里需要注意,PyInit__testc中有两个下划线,它的规则是 PyInit_模块名,因为我们这里假设是私有模块,本身前面有个下划线,
所以这里有两个,如果不是私有包,那只有一个。

###,在调用WinAPI的前面添加:
Py_BEGIN_ALLOW_THREADS;
ret = GetQueuedCompletionStatus(CompletionPort, &NumberOfBytes,
	&CompletionKey, &Overlapped, Milliseconds);
Py_END_ALLOW_THREADS;

意思是:在调用Windows Native API之前释放GIL锁,交出控制权,之后再申请控制权

在解决方案中点击c++工程进行编译,此刻我们编译出Debug版本。它输出到python工程的x64/Debug目录,包含4个文件,其中:
_testc_d.pyd就是c++扩展模块

# 编写python工程

import _testc ...


# 混合调试python和C++工程

在c++工程代码中需要调试的位置打断点,将python设置为启动项目,其中入口文件设置为启动文件 在python代码中打断点,按下F5进入调试


# 安装

写 setup.py,包含自动编译和安装,最后生成whl包

⚠️ **GitHub.com Fallback** ⚠️