2018-12-02 16:05

 版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处、作者信息和本声明,否则将追究法律责任。https://blog.kokojia.com/laoxiaketang/b-1997.html

C++开发python windows版本的扩展模块示例

测试环境介绍和准备

测试环境:

操作系统:windows10

Python版本:3.7.0

VS版本:vs2015社区版(免费)

相关工具下载:

VS版本vs2015社区版(免费)

win10SDK(安装vs2015是可以选择,如果没有安装则需要独立安装)

Python3.7.0 win32 安装文件

本示例不使用vs来编辑,但需要安装vs的编译环境,直接用python的distutils进行编译安装,注意这里安装的python是32位的,所以编译出来库也是32位程序。

首先要检测系统中是否有其他python版本,防止冲突

进入python命令行

import sys

print(sys.path)

 

1543737379417657.png

查看下当前系统路径是否正确,如果是其他路径的版本,可能会对的扩展库开发产生影响。主要是库文件、头文件、dll文件不一致的问题。

1 头文件和库文件

首先创建文件 mymod.c 在文件中添加头文件引用

头文件引用 #include "Python.h",库文件不需要指定,头文件路径在python的安装路径。

 

2 定义模块函数

其中函数参数 self是模块自身,args是python传递的参数列表,返回值定义了一个整形数0,这里会申请空间增加引用计数,交由python来管理这个引用。这里也可以返回NULL,python会收到一个异常。

#include "Python.h"

///模块函数

static PyObject *testmod(PyObject *self,PyObject*args)

{

//返回python的long整形,c语言中引用计数+1,返回值交由python释放

return PyLong_FromLong(0);

}

1543737396541991.png

3 申明模块函数(开放给python)

第一个函数名称,就是开放给python的名称,不一定要与c语言的函数名称一致,但还是尽量一致,方便跟进代码;

第二个是函数指针,默认类型就是PyCFunction函数指针类型,也就是上面的函数类型;

第三个参数是开放给python的函数参数类型,这里我们设置的无参数METH_NOARGS,还可以设置METH_VARARGS 多个参数,METH_KEYWORDS key value参数,设置为METH_KEYWORDS必须与METH_VARARGS一起设置 METH_KEYWORDS|METH_VARARGS ,并且模块函数会增加一个参数存放传进来的参数字典;

第四个参数是函数说明,在python中调用help函数可以读取;

这个定义是一个数据,可以设置多个函数PyMethodDef定义对象

/// 模块函数列表

static PyMethodDef mymod_funcs[] = {

{

"testmod", //函数名称

testmod, //函数指针

METH_NOARGS,//参数标识 无参数,

"testmod function." //函数说明 help(testmod)

},

{0,0,0,0} //数组结尾,可以申请多个函数

};

1543737410842150.png

4 模块定义

///4 模块定义

static PyModuleDef mymod_module = {

PyModuleDef_HEAD_INIT,

"mymod", //模块名

"mymod is first module test", //模块说明 通过help(模块名)

-1, //模块空间,子解释器用,-1不使用

mymod_funcs //模块函数,前面定义的函数申明数组

};

1543737456664793.png

5 添加入口函数

其中PyMODINIT_FUNC 宏在windows中是

PyMODINIT_FUNC __declspec(dllexport) PyObject*,

也就是入口的动态链接库函数,不同于ctypes库,扩展库只有入口函数需要定义__declspec(dllexport)导出函数符号,其他的函数不需要。

PyModule_Create创建python的模块,参数是前面定义的模块,返回直接返回模块对象,在python中所有类型都可以转为PyObject

///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名

PyMODINIT_FUNC PyInit_mymod(void)

{

printf("PyInit_mymod\\n");

///2 模块创建函数 参数 PyModuleDef

return PyModule_Create(&mymod_module);

}

1543737471968300.png

6 编译安装

创建一个文件setup.py

第一行代码导入setup库,其中name是打包的库说明的.egg-info的文件名

version=“1.0” 这个说明文件名的后缀,如果不设置后缀会默认0.0.0

ext_modules=[Extension("mymod", ["mymod.c"] )] 中mymode是对应的模块名称和模块文件名,["mymod.c"]里面是编译为库的源文件,可以是多个文件,这里是一个python的list数组。

from distutils.core import *

setup(

name="mymod", #打包文件名称 库说明文件的文件名

version="1.0",

ext_modules=[Extension("mymod", ["mymod.c"] )]

)

1543737711278241.png

最后运行命令 python setup.py install

1543737621118624.png

编译成功,在当前路径下会生成一个build目录,里面是编译好的内容,应为运行了install命令,所以不仅做了编译还有安装。

扩展库安装的路径:F:\\Python-3.7.0\\Lib\\site-packages

1543737611518294.png

 

7 扩展库调用测试

扩展库编译和按照好后我们写一个python代码来测试

1543737598753799.png

 

这样我们就完成了我们第一个python扩展库的程序

 

 

1543737529600111.png

 




 版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处、作者信息和本声明,否则将追究法律责任。https://blog.kokojia.com/laoxiaketang/b-1997.html

评论

kvc636757024

#1

kvc636757024

http://v.qq.com/x/search/?q=%E5%8D%8E%E7%BA%B3%E5%B9%B3%E5%8F%B0_18183615678
2020/06/26 13:59回复
博主资料
老夏课堂
  • 原创:1 篇
  • 转载:0 篇
  • 译文:0 篇
  • 热度:1W

文章存档

最新发表