一、问题发生环境
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使用方法
下面记录一下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模块测试一下:文章来源:https://www.toymoban.com/news/detail-455975.html
import test
test.hello()
输出Hello World!,完美。文章来源地址https://www.toymoban.com/news/detail-455975.html
到了这里,关于python distutils打包C/C++模块,执行python setup.py build_ext --inplace时报错cl的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!