最近看开源项目时学习了一下用C/C++写python模块,顺便把学习进行一下总结,废话少说直接开始:

环境:windows、python2.78、VS2010或MingW

1 创建VC工程

(1) 打开VC6.0或VS2008,然后File-->New-->Project-->Win32 DLL Project。建立一个Empty Project,比如testClass,一路确定。

(2) 之后向工程添加python头文件目录及库文件目录,如头文件目录:F:\python278\include,库文件目录:F:\python278\libs

(3) 添加一个C++或C源文件,如工程中有用到类,则添加的必须是C++文件,这里直接添加main.cpp

#include <Python.h>
#include <iostream>
#include <sstream>
#include <structmember.h>
#include <windows.h> using namespace std; typedef struct _CScore
{
PyObject_HEAD
char *m_szName;
float m_dMath;
float m_dEnglish;
}CScore; static PyMemberDef CScore_DataMembers[] = { //类/结构的数据成员的说明.
{"m_szName", T_STRING, offsetof(CScore, m_szName), , "The Name of instance"},
{"m_dMath", T_FLOAT, offsetof(CScore, m_dMath), , "The Math score of instance."},
{"m_dEnglish", T_FLOAT, offsetof(CScore, m_dEnglish), , "The English score of instance."},
{NULL, NULL, NULL, , NULL}
}; //////////////////////////////////////////////////////////////
// CScore类的所有内置、构造方法.
//
static void CScore_init(CScore* Self, PyObject* pArgs) //构造方法.
{
const char* Name = ;
if(!PyArg_ParseTuple(pArgs, "sff", &Name, &Self->m_dMath, &Self->m_dEnglish))
{
cout<<"Parse the argument FAILED! You should pass correct values!"<<endl;
return ;
} Self->m_szName = new char[strlen(Name) + ];
strcpy(Self->m_szName, Name);
} static void CScore_Destruct(CScore* Self) //析构方法.
{
if(Self->m_szName){
delete [] Self->m_szName; //先释放其字符指针对象.
}
OutputDebugString(TEXT("destroy!!!")); //如果还有PyObject*成员的话,要一并释放之.
//如:Py_XDECREF(Self->Member);
Py_TYPE(Self)->tp_free((PyObject*)Self); //释放对象/实例.
} static PyObject* CScore_Str(CScore* Self) //调用str/print时自动调用此函数.
{
ostringstream OStr;
OStr<<"Name : "<<Self->m_szName<<endl
<<"Math : "<<Self->m_dMath<<endl
<<"English : "<<Self->m_dEnglish<<endl;
string Str = OStr.str();
return Py_BuildValue("s", Str.c_str());
} static PyObject* CScore_Repr(CScore* Self) //调用repr内置函数时自动调用.
{
return CScore_Str(Self);
} ////////////////////////////////////////////////////////////
// CScore类的所有Get方法.
//
static PyObject* CScore_GetName(CScore* Self)
{
return Py_BuildValue("s", Self->m_szName);
} static PyObject* CScore_GetMath(CScore* Self)
{
return Py_BuildValue("f", Self->m_dMath);
} static PyObject* CScore_GetEnglish(CScore* Self)
{
return Py_BuildValue("f", Self->m_dEnglish);
} ////////////////////////////////////////////////////////////
// CScore类的所有Set方法.
//
static PyObject* CScore_SetMath(CScore* Self, PyObject* Argvs)
{
Py_INCREF(Py_None);
if(!PyArg_ParseTuple(Argvs, "f", &Self->m_dMath))
{
cout<<"Parse the argument FAILED! You should pass correct values!"<<endl;
return Py_None;
} return Py_None;
} static PyObject* CScore_SetEnglish(CScore* Self, PyObject* Argvs)
{
Py_INCREF(Py_None);
if(!PyArg_ParseTuple(Argvs, "f", &Self->m_dEnglish))
{
cout<<"Parse the argument FAILED! You should pass correct values!"<<endl;
return Py_None;
} return Py_None;
} static PyObject* CScore_PrintInfo(CScore* Self)
{
cout<<"The scores as follows:"<<endl
<<"=============================="<<endl
<<"Name : "<<Self->m_szName<<endl
<<"Math : "<<Self->m_dMath<<endl
<<"English : "<<Self->m_dEnglish<<endl
<<"=============================="<<endl; Py_XINCREF(Py_None);
return Py_None;
} static PyMethodDef CScore_MethodMembers[] = //类的所有成员函数结构列表.
{
{"GetName", (PyCFunction)CScore_GetName, METH_NOARGS, "Get the name of instance."},
{"GetMath", (PyCFunction)CScore_GetMath, METH_NOARGS, "Get the math score of instance."},
{"GetEnglish", (PyCFunction)CScore_GetEnglish, METH_NOARGS, "Get the english score of isntance."}, {"SetMath", (PyCFunction)CScore_SetMath, METH_VARARGS, "Set the math score of instance."},
{"SetEnglish", (PyCFunction)CScore_SetEnglish, METH_VARARGS, "Set the english of instance."}, {"PrintInfo", (PyCFunction)CScore_PrintInfo, METH_NOARGS, "Print all information of instance."}, {NULL, NULL, NULL, NULL}
}; ////////////////////////////////////////////////////////////
// 类/结构的所有成员、内置属性的说明信息.
//
static PyTypeObject CScore_ClassInfo =
{
PyVarObject_HEAD_INIT(NULL, )
"Module.MyCppClass", //可以通过__class__获得这个字符串. CPP可以用类.__name__获取.
sizeof(CScore), //类/结构的长度.调用PyObject_New时需要知道其大小.
,
(destructor)CScore_Destruct, //类的析构函数.
,
,
,
,
(reprfunc)CScore_Repr, //repr 内置函数调用。
,
,
,
,
,
(reprfunc)CScore_Str, //Str/print内置函数调用.
,
,
,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //如果没有提供方法的话,为Py_TPFLAGS_DEFAULE
"MyCppClass Objects---Extensioned by C++!", //__doc__,类/结构的DocString.
,
,
,
,
,
,
CScore_MethodMembers, //类的所有方法集合.
CScore_DataMembers, //类的所有数据成员集合.
,
,
,
,
,
,
(initproc)CScore_init, //类的构造函数.
,
}; ////////////////////////////////////////////////////////////
// 此模块的说明信息. 由于我用的python2所以直接把该部分进行注释
//
/*static PyModuleDef ModuleInfo =
{
PyModuleDef_HEAD_INIT,
"My C++ Class Module", //模块的内置名--__name__.
"This Module Created By C++--extension a class to Python!", //模块的DocString.__doc__
-1,
NULL, NULL, NULL, NULL, NULL
};*/ int add(int x, int y)
{
return x+y;
} static PyObject* W_add(PyObject* self, PyObject* args) {
int x;
int y;
if(!PyArg_ParseTuple(args, "i|i", &x, &y)) {
return NULL;
} else {
return Py_BuildValue("i", add(x, y));
}
} static PyMethodDef module_methods[] = {{"add", W_add, METH_VARARGS, "a function from C"},{NULL, NULL, , NULL}}; PyMODINIT_FUNC inittestClass(void) //模块外部名称为--CppClass
{
PyObject* pReturn = ;
CScore_ClassInfo.tp_new = PyType_GenericNew; //此类的new内置函数—建立对象. /////////////////////////////////////////////////////
// 完成对象类型的初始化—包括添加其继承特性等等。
// 如果成功,则返回0,否则返回-1并抛出异常.
if(PyType_Ready(&CScore_ClassInfo) < )
return; pReturn = Py_InitModule3("testClass", module_methods, "Example module that creates an extension type.");
if(pReturn == NULL)
return;
Py_INCREF(&CScore_ClassInfo);
PyModule_AddObject(pReturn, "CScore", (PyObject*)&CScore_ClassInfo); //将这个类加入到模块的Dictionary中.
return;
}

main.cpp

之后修改VC工程导出文件后缀名为pyd

2 使用testClass模块

编译工程生成testClass.pyd模块文件,进入到导出文件目录,并启动python

导入testClass模块并查看其详细信息

模块详细使用

3 其他编译方式

下面介绍另一种用Python Script来生成.pyd文件的方法,新建一个Python脚本——CreatePyd.py,其内容如下:

from distutils.core import setup, Extension
ModuleInfo = Extension("testClass", sources = [r"main.cpp"])
setup(name = "testClass",
version = "1.0",
description = "This module created by C++ weiwei.Zhao",
author = 'weiwei.zhao',
author_email = 'weiwei22844@hotmail.com',
license = "You can copy this program to anywhere.",
url = "http://zhaoweiwei.top",
long_description = '''This is really just a demo!''',
platforms = "Windows",
ext_modules = [ModuleInfo]
)

CreatePyd.py

内容解释:先导入所需的Python模块,然后用Extension函数关联一个Cpp源文件一个要生成的模块名——注意:没有.pyd后缀。然后调用setup函数生成一个名字name为testClass的模块,版本version为1.0,描述description,作者信息author,作者邮箱author_email,还其平台platforms等等有用的信息!

最后调用:python CreateDLL.py build

经过编译后,就会新生成一个build目录,在build/lib.win32-2.7下你可以找到testClass.pyd文件。

需要注意的是编译脚本默认使用VS编译器,所以电脑上要安装VS,如果电脑上没有安装VS而是有MingW环境,则类似的可以使用MingW环境中gcc进行编译:

注意:为了使相关程序都能顺利找见,上图是在MingW的Shell命令行,而不是普通的windows Command命令行。

4 模块部署安装

一般来说,setup.py参数说明

#python setup.py build      # 编译

#python setup.py install     # 安装

#python setup.py sdist      # 生成压缩包(zip/tar.gz)

#python setup.py bdist_wininst   #生成NT平台安装包(.exe)

#python setup.py bdist_rpm  #生成rpm包

或者直接"bdist 包格式",格式如下:

#python setup.py bdist --help-formats

--formats=rpm       RPM distribution

--formats=gztar     gzip'ed tar file

--formats=bztar     bzip2'ed tar file

--formats=ztar     compressed tar file

--formats=tar       tar file

--formats=wininst   Windows executable installer

--formats=zip       ZIP file

下图说明了windows安装程序生成过程,在dist目录下有windows的安装程序testClass-1.0.win32-py2.7.exe

需要说明的是如果生成的testClass.pyd依赖于其他库文件,如在我的环境下用MingW生成的testClass.pyd要依赖libgcc_s_dw2-1.dll和libstdc++-6.dll两个文件,生成安装包时需把这两个文件和testClass.pyd放到一起,如放到build/lib.win32-2.7目录下,之后生成的安装文件testClass-1.0.win32-py2.7.exe会包含着两个文件,如果不这样做在导入testClass时会导致导入失败,提示类似:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: DLL load failed: 找不到指定的程序。

结束语

以上的总结参考了部分网友的博文,主要如下,一并感谢:

http://blog.csdn.net/arnozhang12/article/details/5409155

http://blog.csdn.net/carolzhang8406/article/details/6925745

使用C/C++写Python模块的更多相关文章

  1. 孤荷凌寒自学python第七十九天开始写Python的第一个爬虫9并使用pydocx模块将结果写入word文档

    孤荷凌寒自学python第七十九天开始写Python的第一个爬虫9 (完整学习过程屏幕记录视频地址在文末) 今天在上一天的基础上继续完成对我的第一个代码程序的书写. 到今天终于完成了对docx模块针对 ...

  2. python 写 excel 模块 : xlwt

    主要来自:[ python中使用xlrd.xlwt操作excel表格详解 ] 为了方便阅读, 我将原文两个模块拆分为两篇博文: [ python 读 excel 模块: xlrd ] [ python ...

  3. python 学习第五天,python模块

    一,Python的模块导入 1,在写python的模块导入之前,先来讲一些Python中的概念性的问题 (1)模块:用来从逻辑上组织Python代码(变量,函数,类,逻辑:实现一个功能),本质是.py ...

  4. 安装第三方Python模块,增加InfoPi的健壮性

    这3个第三方Python模块是可选的,不安装的话InfoPi也可以运行. 但是如果安装了,会增加InfoPi的健壮性. 目录 1.cchardet    自动检测文本编码 2.lxml    用于解析 ...

  5. Python基础篇【第5篇】: Python模块基础(一)

    模块 简介 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就 ...

  6. python模块学习心得

    初始模块 1.什么是模块 模块是用来实现某项功能的一大堆代码,为什么会有模块呢?过程式编程的时候为了减少程序员编程代码的重复性,就利用函数的调用减少了代码的重复性,但是某些时候程序会过于的庞大,我们会 ...

  7. Python模块常用的几种安装方式

    Python模块安装方法 一.方法1: 单文件模块直接把文件拷贝到 $python_dir/Lib 二.方法2: 多文件模块,带setup.py 下载模块包,进行解压,进入模块文件夹,执行:pytho ...

  8. 6.python模块(导入,内置,自定义,开源)

    一.模块 1.模块简介 模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py.模块可以被别的程序引入,以使用该模块中的函数等功能.这也是使用python标准库的方法. 类似于函数式编程和面向过 ...

  9. Python模块学习

    6. Modules If you quit from the Python interpreter and enter it again, the definitions you have made ...

随机推荐

  1. 如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成

    阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...

  2. ASP.NET Core 1.1.0 Release Notes

    ASP.NET Core 1.1.0 Release Notes We are pleased to announce the release of ASP.NET Core 1.1.0! Antif ...

  3. 为你的Web程序加个启动画面

    .Net开发者一定熟悉下面这个画面: 这就是宇宙第一IDE Visual Studio的启动画面,学名叫Splash Screen(或者Splash Window).同样,Javar们一定对Eclip ...

  4. ASP.NET MVC5+EF6+EasyUI 后台管理系统(81)-数据筛选(万能查询)

    系列目录 前言 听标题的名字似乎是一个非常牛X复杂的功能,但是实际上它确实是非常复杂的,我们本节将演示如何实现对数据,进行组合查询(数据筛选) 我们都知道Excel中是如何筛选数据的.就像下面一样 他 ...

  5. .NET Core的日志[1]:采用统一的模式记录日志

    记录各种级别的日志是所有应用不可或缺的功能.关于日志记录的实现,我们有太多第三方框架可供选择,比如Log4Net.NLog.Loggr和Serilog 等,当然我们还可以选择微软原生的诊断框架(相关A ...

  6. Asp.net Core准备工作

    1.安装环境 安装.Net Core SDK 安装VS2015 Update3 安装DotNetCore.1.0.1-VS2015Tools.Preview2.0.2.exe 2.新建Core工程 项 ...

  7. Angular2 Hello World 之 2.0.0-beta.14

    公司现在采用angualrjs开发一些web应用,采用的是angular1,现在angular2已经差不多了,听说最近rc6已经出来了……其实感觉好慢啊!之前也做过一些anglar2的例子,但是没有记 ...

  8. 最近在玩linux时 yum 遇到了问题

    主要是软件源出现了问题 我做的方式可能比较粗暴 ls -l /etc/yum.repos.d/       /*查看软件源*/ rm -rf /etc/yum.repos.d/   /*全删了*/ m ...

  9. Android快乐贪吃蛇游戏实战项目开发教程-04虚拟方向键(三)三角形按钮效果

    该系列教程概述与目录:http://www.cnblogs.com/chengyujia/p/5787111.html 一.知识点讲解 当我们点击系统自带的按钮时,按钮的外观会发生变化.上篇博文中我们 ...

  10. Oracle 用Drapper进行like模糊传参查询需要在参数值前后带%符合

    Oracle 用Drapper进行like模糊传参查询需要在参数值前后带%符合   string sqlstr="select * from tblname where name like ...