您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 经营企划 > sip C++扩展python
1/24程序打包历程:阶段一:手动打包:过程:第一块:python调用c++程序。例子1.VS2008-建立工程mb(VisualC++下的Win32选择win32Project)-next-ApplicationSettings的Applicationtype中选择DLL.确定就OK了。然后进行搭建环境:点击菜单工具-选项,打开选项对话框,选择项目和解决方案-VC++目录,添加python的include目录(我的机器上是F:\Python26\include),然后选择库文件,添加python的libs目录(我的机器上是F:\Python25\libs);mb.cpp如下:#includestdafx.h#includePython.h#pragmacomment(lib,pytho26.lib)staticPyObject*mb_showMsg(PyObject*self,PyObject*args);externC__declspec(dllexport)voidinitmb(){staticPyMethodDefmbMethods[]={{showMsg,mb_showMsg,METH_VARARGS},{NULL,NULL,NULL}};//PyObject*m=Py_InitModule(mb,mbMethods);PyObject*m=PyModule_Create(&mbMethods);}staticPyObject*mb_showMsg(PyObject*self,PyObject*args){2/24constchar*msg=NULL;if(!PyArg_ParseTuple(args,s,&msg))returnNULL;//intr=::MessageBox(NULL,hello,Caption:FormCmodule,MB_ICONINFORMATION|MB_OK);intr=::MessageBox(NULL,msg,Caption:FormCmodule,MB_ICONINFORMATION|MB_OK);returnPy_BuildValue(i,r);}最后编译运行。把生成的mb.dll,修改后缀成mb.pyd,然后拷贝到python的DLLs目录下,打开idle(python的交互程序),写入代码:importmbmb.showMsg(Python'sreallyamazing,Ikinddaloveit!)可以看到弹出来一个MessageBox。这样就完成了Python中调用C++代码。如下也是可以的:例子2.1。在vc6中建立一个dll的project。假定我们的module的名字是mytest.那么我们的dll名字就是mytest.dll。这个是必须的。2。用c写我们想要实现的部分。步骤如下#includePython.h这个是必须的。python的类型都在这里定义。类似写window程序一定要包含windows.h一样。所以,在vc里一定要设置好include的路径。这个文件在Python26\include\下面。4。写我们想要实现的函数。比如我们想要实现两个c的函数,strlen和strcat。我们必须分别包装他们。命名为my_strlen和my_strcat。先声明:staticPyObject*my_strlen(PyObject*self,PyObject*args);staticPyObject*my_strcat(PyObject*self,PyObject*args);一定声明为static,把他们限制在这个文件范围里。几乎所有的参数都是PyObject类型。在python,每个东西都是object。这两个函数的定义是这样的:staticPyObject*my_strlen(PyObject*self,PyObject*args){char*string;intlen;if(!PyArg_ParseTuple(args,s,&string))returnNULL;len=strlen(string);3/24returnPy_BuildValue(i,len);}staticPyObject*my_strcat(PyObject*self,PyObject*args){char*string1;char*string2;char*newstring;if(!PyArg_ParseTuple(args,s|s,&string1,&string2))returnNULL;newstring=strcat(string1,string2);returnPy_BuildValue(s,newstring);}第一个参数是self,这个是python用的,每个函数都要有。我们暂时不管。args是一个参数列表。她把所有的参数都整合成一个string。所以我们需要从这个string里来解析我们的参数。PyArg_ParseTuple来完成这个任务。第一个参数是args,就是我们要转换的参数。第二个是格式符号。“s”代表是个string。从args里提取一个参数就写s,两个的话就写s|s,如果是一个string,一个int,就写s|i,和printf差不多。第三个参数就是提取出来的参数放置的真正位置。必须传递这个参数的地址。对于my_strcat,他将提取两个参数。分别是string1和string2。然后调用真正的我们的实现。分别是strlen和strcat。调用完之后我们需要返回结果。这个结果是c的type或者是我们自己定义的类型。必须把他转换成PyObject,让python认识。这个用Py_BuildValue来完成。他是PyArg_ParseTuple的逆过程。他的第一个参数和PyArg_ParseTuple的第二个参数一样,是个格式化符号。第三个参数是我们需要转换的参数。Py_BuildValue会把所有的返回只组装成一个tutple给python。实际上,我们只是把我们想要实现的部分调用python提供的api来封装了一下。但是python并不知道怎么用这些函数。我们还需要做一些工作。staticPyMethodDefmytestMethods[]={{mystrlen,my_strlen,METH_VARARGS,WeteststrlenofC},{mystrcat,my_strcat,METH_VARARGS,WeteststrcatofC},{NULL,NULL,0,NULL}};这个是一个c的结构。他来完成一个映射。我们需要把我们扩展的函数都映射到这个表里。4/24表的第一个字段是python真正认识的。是python里的方法名字。第二个字段是python里的这个方法名字的具体实现的函数名。在python里调用mystrlen,真正执行的是用c写的my_strlen函数。第三个字段是METH_VARARGS,他告诉python,mystrlen是调用c函数来实现的。第四个字段是这个函数的说明。如果你在python里来help这个函数,将显示这个说明。相当于在python里的函数的文档说明。我们建立了这个映射表。这个表是在python导入我们的这个module的时候来用的。但是python是如何来调用这个表的呢。他通过这个函数_declspec(dllexport)voidinitmytest(){(void)Py_InitModule(mytest,mytestMethods);}注意,这个函数的名字不能改动。必须是init+模块名字。我们的模块名字是mytest。所以这个函数是initmytest()。这个函数应该被导出。所以使用_declspec(dllexport)。这样python在导入mytest的模块时候,才会找到这个函数,并调用。这个函数调用Py_InitModule来将模块名字和映射表结合在一起。他表示,mytest这个模块使用mytestMethods这个映射表。python应该这样导入我们的module的:a.当我们importmytest的时候。python装载这个module的dll。在这里是mytest.dllb.然后在这个dll里调用,initmytest函数来建立一个映射表。如果这个initmytest函数不实现或者没有导出。就不能成功把这个module导入到python里。c.python从映射表知道这个模块实现了几个方法。并且名字分别是什么。当调用他们的时候,找到相应的c的函数。写完这些代码以后,我们可以在vc6里编译这个dll,注意,必须编译成release版本。并且链接python26.lib。如果是debug版本他将会找python26_d.lib。编译的dll名字是mytest.dll。如果不是的话,在vc里改动link的设置。把mytest.dll拷到python26的lib目录下,或者python能搜索到的路径下。进入python的shellimportmytest.dllmytest.mystrlen(123)3mytest.mystrcat(123,456)123456#includePython.h5/24staticPyObject*my_strlen(PyObject*self,PyObject*args);staticPyObject*my_strcat(PyObject*self,PyObject*args);staticPyMethodDefmytestMethods[]={{mystrlen,my_strlen,METH_VARARGS,WeteststrlenofC},{mystrcat,my_strcat,METH_VARARGS,WeteststrcatofC},{NULL,NULL,0,NULL}};staticPyObject*my_strlen(PyObject*self,PyObject*args){char*string;intlen;if(!PyArg_ParseTuple(args,s,&string))returnNULL;len=strlen(string);returnPy_BuildValue(i,len);}staticPyObject*my_strcat(PyObject*self,PyObject*args){char*string1;char*string2;char*newstring;if(!PyArg_ParseTuple(args,s|s,&string1,&string2))returnNULL;newstring=strcat(string1,string2);returnPy_BuildValue(s,newstring);}_declspec(dllexport)voidinitmytest(){(void)Py_InitModule(mytest,mytestMethods);}6/24第二块:在C++程序中嵌入Python1.高层次嵌入:引用解释器Python标准的外部调用方法并不复杂,在Python的文档中可以查到。最简单的调用方式如下:#includePython.hintmain(intargc,char*argv[]){Py_Initialize();PyRun_SimpleString(fromtimeimporttime,ctime\nprint'Todayis',ctime(time())\n);//此处只能使用这个函数,别的函数因版本的不同,不可使用Py_Finalize();return0;}Py_Initialize();启动虚拟机,Py_Finalize();终止它。PyRun_SimpleString用于执行语句。Boost延续了这一方式,并着眼于将交互过程变得更简单些。但是这里面涉及到python版本中的函数问题。但是这个只可以在python31中运行。2.低层
本文标题:sip C++扩展python
链接地址:https://www.777doc.com/doc-4831139 .html