赞
踩
python可以把C/C++代码编译并打包为pyd模块,从而可以使python脚本直接调用C/C++模块功能。
我在执行python setup.py build_ext --inplace时遇到了缺失cl.exe的错误提示,然后用pip安装了cl。
再次编译,提示cl: error: no such option: -I,改变cl版本仍然不行,百思不得其解。
后来意识到C/C++模块的编译实际上还是python调用专门的C/C++编译器进行编译的,在另一台电脑上全新的环境上运行,发现系统默认执行的是Microsoft Visual C++ (14.0以上版本)下的cl来编译C/C++,而不是python下的cl。
Microsoft C++ 生成工具 - Visual Studio
下Microsoft生成工具,具体安装方法可以搜索“解决报错 Microsoft Visual C++ 14.0 is required”,网上有很多相关文档。
之后就可以正常调用MSVC的cl来编译打包pyd啦。
下面记录一下python distutils的使用方法。
创建一个test文件夹。
编辑一个test.c,随便写个Hello world就麻烦:
include <Python.h>,以PyMODINIT_FUNC为标志写一个Python Module init函数来Create一个Python Module “test”。
其中,PyObject、PyModule_Create等都定义在Python.h中,并且Python.h已经include了stdio.h。
- PyMODINIT_FUNC PyInit_test(void)
- {
- PyObject *m;
- m = PyModule_Create(&test);
- if (m == NULL)
- {
- return Py_BuildValue("");
- }
-
- return m;
- }
定义Python Module “test”,test_methods指向test module的方法。
- PyMethodDef test_methods[] =
- {
- {"hello", hello, METH_VARARGS, "print a hello world"},
- {NULL, NULL, 0, NULL}
- };
-
- struct PyModuleDef test =
- {
- PyModuleDef_HEAD_INIT,
- "test", // 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. /
- test_methods // A pointer to a table of module-level functions, described by PyMethodDef values. Can be NULL if no functions are present. /
- };
终于可以写Hello World了,注意返回值类型应为PyObject*,直接把全部代码放上来吧。
- #include <Python.h>
-
- PyObject* hello()
- {
- printf("Hello World!");
-
- return Py_True;
- }
-
- PyMethodDef test_methods[] =
- {
- {"hello", hello, METH_VARARGS, "print a hello world"},
- {NULL, NULL, 0, NULL}
- };
-
- struct PyModuleDef test =
- {
- PyModuleDef_HEAD_INIT,
- "test", // 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. /
- test_methods // A pointer to a table of module-level functions, described by PyMethodDef values. Can be NULL if no functions are present. /
- };
-
- PyMODINIT_FUNC PyInit_test(void)
- {
- PyObject *m;
- m = PyModule_Create(&test);
- if (m == NULL)
- {
- return Py_BuildValue("");
- }
-
- return m;
- }

在test目录下创建一个setup.py,编辑如下:
- from distutils.core import setup, Extension
-
-
- module1 = Extension('test',
- sources = ['test.c'])
-
- setup (name = 'test',
- version = '1.0',
- description = 'test extention',
- ext_modules = [module1])
name、version等都不必要,只有ext_modules必要。
执行python setup.py build_ext --inplace,生成test.cp38-win_amd64.pyd,pyd就是python dll,可以直接被python脚本调用的。
最后写个python脚本test.py调用一下test模块测试一下:
- import test
-
- test.hello()
输出Hello World!,完美。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。