本文源自:(1条消息) 浅谈Python C扩展_fitzzhang的博客-CSDN博客_c扩展python
由于不同windows平台上或不同的sw版本, 会出现不同的结果.
本文是使用的环境如下:
1. python 3.10
2.swig-4.0.2
3.Visual Studio 2022 Community
Visual Studio: IDE and code editor for software developers and Teams (microsoft.com)
4.window版本 (msc_ver == '1929')
正式开始前, 修改的配置点:
1. 确认mingw的环境变量配置
path中添加 C:\MinGW\bin\
2. 确认python的相关环境变量配置
3.添加distutils.cfg
使用C ++编译器选项安装MinGW添加C:\MinGW\bin到您的路径在中PYTHONPATH\Lib\distutils,创建一个文件distutils.cfg并添加以下行:
[build]
compiler = mingw32
4.cygwinccompiler.py 83行后插入
elif msc_ver == '1700':
# Visual Studio 2012 / Visual C++ 11.0
return ['msvcr110']
elif msc_ver == '1800':
# Visual Studio 2013 / Visual C++ 12.0
return ['msvcr120']
elif msc_ver == '1929':
# Visual Studio 2015 / Visual C++ 14.0
# "msvcr140.dll no longer exists" http://blogs.msdn.com/b/vcblog/archive/2014/06/03/visual-studio-14-ctp.aspx
return ['vcruntime140']
其中msc_ver=='1929'是为了匹配当前的系统版本, 但是动态链接库还是使用vcruntime140, 安装的Visual Studio 2022 Community会包含这部分.
经过上面的准备工作后, 可以进行后续的步骤了.
原文中的代码直接编译会遇到很多问题,经过一番摸索和网络上寻求答案后, 修改如下:
example.cpp源文件
#include <Python.h>
static PyObject* example_mul(PyObject* self, PyObject*args)
{
float a, b;
if(!PyArg_ParseTuple(args, "ff", &a, &b))
{
return NULL;
}
return Py_BuildValue("f", a*b);
}
static PyObject* example_div(PyObject* self, PyObject*args)
{
float a, b;
if(!PyArg_ParseTuple(args, "ff", &a, &b))
{
return NULL;
}
return Py_BuildValue("f", a/b); // to deal with b == 0
}
static char mul_docs[] = "mul(a, b): return a*b\n";
static char div_docs[] = "div(a, b): return a/b\n";
static PyMethodDef example_methods[] =
{
{"mul", (PyCFunction)example_mul, METH_VARARGS, mul_docs},
{"div", (PyCFunction)example_div, METH_VARARGS, div_docs},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef examples =
{
PyModuleDef_HEAD_INIT,
"example", /* name of module */
NULL, /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
example_methods
};
PyMODINIT_FUNC PyInit_example(void)
{
/*Py_InitModule3("example", example_methods, "Extension module example!");*/
return PyModule_Create(&examples);
}
主要修改点为:Py_InitModule3已经无法找到,所以变异时会报错,替换使用PyModuleDef搭配PyModule_Create, 重命名init function为PyInit_xxxx(此处已经命名为PyInit_example), 从而可以成功编译.
setup.py源文件
from distutils.core import setup, Extension
setup(name="exampleAPP", version="1.0", ext_modules=[Extension("example", ["example.cpp"])])
注意: setup.py中的Extenson中name(example)一定要和PyInit_xxxx中的xxxx完全一样.
cmd 窗口切换到存放这2个文件的路径, 然后用如下命令编译安装:
python setup.py install --user
添加--user可以规避安装过程中的权限问题.
安装成功后,就会在python_path/Lib/site-packages下面生成example.cp310-win_amd64.pyd这个模块和exampleAPP-1.0-py3.10.egg-info这个文件,就可以导入和使用了
开始测试:test_example.py源文件
import example
print('test example start running.\n')
aa = example.mul(5,2)
print(aa)
bb = example.div(5,2)
print(bb)
运行结果如下
简单测试可成功.