怎样搭建免费网站,什么网站做网页好,电器网站建设免费咨询,吉林建设网站C调用python在C/C中嵌入Python#xff0c;可以使用Python提供的强大功能#xff0c;通过嵌入Python可以替代动态链接库形式的接口#xff0c;这样可以方便地根据需要修改脚本代码#xff0c;而不用重新编译链接二进制的动态链接库。至少你可以把它当成文本形式的动态链接库…C调用python在C/C中嵌入Python可以使用Python提供的强大功能通过嵌入Python可以替代动态链接库形式的接口这样可以方便地根据需要修改脚本代码而不用重新编译链接二进制的动态链接库。至少你可以把它当成文本形式的动态链接库需要的时候还可以改一改只要不改变接口 C的程序一旦编译好了再改就没那么方便了。第一种方式通过找到Python模块类方法构造参数来调用。第二中方式就是通过构造出一个Python的脚本用python引擎来执行。第一种方式可能更为优雅符合大多数的反射调用的特点。(如c#的反射机制c#调用Comc#调用javascript脚本等)。一个问题两种语言互相调用的时候需要做数据结构(如基本类型字符串整数类型等以及自定义的类等类型)间的转换共享内存中的一个对象。比如如何将C的对象实例传入python中并在python中使用。c和python并不在一个进程中因此可以使用boost的shared_ptr来实现。Python调用C换句话说就是需要把C封装成Python可以“理解”的类型。同理可知C怎么去调用Python脚本。下面这个例子主要是演示了c调用python可以在c中形成一个python脚本然后利用PyRun_SimpleString调用;并且构造一个c的对象传入到python中并在python的脚本中调用其函数。安装python3.4然后配置系统环境变量。安装Visual Studio2010(注意可以不用安装其它好多东西只要安装c就可以了)。[Visual Studio相关设置]vs中新建一个win32控制台应用程序一路确定完成。1. c调用python需要在vs2010中的cpp文件中加入这个头文件在python安装目录Python\include下要成功引入就要把Python.h的头文件目录(如D:\python3.4.2\include放在菜单 项目 属性 C/C 常规 附加包含目录下(或者右键项目)2. 还需要一个python34.lib如果不导入的话会提示你出现这个文件的缺失。文件在python\libs下找到此文件之后进入VS2010菜单 项目 属性 配置属性 VC目录 库目录把刚才的绝对路径(如D:\python3.4.2\libs)添加进去此时变成这样的了D:\python3.4.2\libs;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib。这样就可以在VC程序中执行python文件了。或者把D:\python3.4.2\libs放进项目 属性 配置属性 链接器 常规 附加库目录中。Note: 上面的设置是对某个模式生效如果将运行模式从debug改成了release要再进去设置否则设置不成功。将PythonInvoke.cpp文件改成下面的代码用于调用python程序helloworld// PythonInvoke.cpp : 定义控制台应用程序的入口点。#include stdafx.h#includevoid main(){Py_Initialize(); /*初始化python解释器,告诉编译器要用的python编译器*/PyRun_SimpleString(import helloworld); /*调用python文件*/PyRun_SimpleString(helloworld.printHello());/*调用python文件中的函数*/Py_Finalize(); /*结束python解释器释放资源*/system(pause);}Note: 当python代码有错误时PyImport_ImportModule函数返回NULL另一种调用方式的代码#include//前面所做的一切配置都是为了调用这个头文件和相关库#includeusing namespace std;int main(){Py_Initialize();//使用python之前要调用Py_Initialize();这个函数进行初始化PyObject * pModule NULL;//声明变量PyObject * pFunc NULL;// 声明变量pModule PyImport_ImportModule(helloworld);//这里是要调用的文件名pFunc PyObject_GetAttrString(pModule, Hello);//这里是要调用的函数名PyEval_CallObject(pFunc, NULL);//调用函数Py_Finalize();//调用Py_Finalize这个根Py_Initialize相对应的。return 0;}在项目源文件中添加文件命令为helloworld.pydef printHello():print(Hello World!).py文件保存在.cpp同目录下Note: 不能将python文件的名字命名为test.py,否则报错由于test.py是python内置python脚本文件也就是python有自己的test.py文件并且其优先级比你的高。。如果你安装的python是64位的则vs2010中需要把解决方案平台定位‘X64’的模式下否则配置不成功。报错fatal error LNK1112: 模块计算机类型“X86”与目标计算机类型“x64”冲突。[fatal error LNK1112]release模式下运行不用设置太多东西修改运行选项Debug改为Releasewin32下拉配置新建x64一路确定注意执行下面之前要在release模式下再设置一次VS2010的配置运行运行成功1. Debug下python/libs目录下的python34.lib需要复制并重命名为python34_d.lib的形式设置项目 属性 配置属性 链接器 输入 附加依赖库 python34_d.lib。为什么会有python34.lib和python34_d.lib的差别就是因为:python_d.lib是 库的调试后形式当我们以debug模式编译工程时python就用这个lib文件但是这个文件是不可用 的。对于这点最快的办法就是强制要求python在任何情况下都是用非调试版本就可以了。就是说不重命名的解决方法对python头文件python/include/pyconfig.h进行修改# if defined(_DEBUG)# pragma comment(lib,python34_d.lib)# elif defined(Py_LIMITED_API)# pragma comment(lib,python3.lib)# else# pragma comment(lib,python34.lib)# endif /* _DEBUG */将DEBUG条件下的lib由python34_d.lib改为python34.lib.# if defined(_DEBUG)# pragma comment(lib,python34.lib)2. 64位debug下的方案解决右键项目名点击属性弹出项目属性页找到链接器—高级修改右侧的目标计算机选择有X64的那个选项。如果没有则选择编译器Configuration Manager中new添加amd64等平台然后工程属性中选择x64。这一步好像也不用只要在运行时选择x64就可以了。见3.运行。Note: 属性 - 链接器 - 命令行 -附加选项:如果里面有/MACHINE:I386之类的,要删了。3. 32位库改成64位库项目 属性 配置属性 Vc目录 库目录这里要将32位库改成64位库相当重要$(VCInstallDir)lib\amd64$(VCInstallDir)atlmfc\lib\amd64$(WindowsSdkDir)lib\x64如将D:\python3.4.2\libs;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib换成D:\python3.4.2\libs;$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSdkDir)lib\x64;$(FrameworkSDKDir)\lib没有这样设置会报错msvcprtd.lib(MSVCP100D.dll) : fatal error LNK1112: module machine type ‘X86’ conflicts with target machine type ‘x64’msvcprtd.lib(MSVCP100D.dll) : fatal error LNK1112: 模块计算机类型“X86”与目标计算机类型“x64”冲突3. 运行右键项目名选择清理解决方案清理完成之后重新生成解决方案然后选择X64平台编译器去debug便可以调试成功。c调用python时报错LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏这个是由于日志文件引起的可以将项目\属性\配置属性\清单工具\输入和输出\嵌入清单原来是“是”改成“否”。或者将项目\属性\配置属性\链接器\清单文件\生成清单原来是“是”改成“否”。如果仍然无效判断是否已经安装了VS2012如果已经安装需要安装VS2010 sp1补丁。但是如果程序要加写rc必须带清单才能正常使用。所以这种治标不治本的方法失效了。还有一种解决方案出现这个问题的原因可能是因为系统最近多次更新出现了两个版本的cvtres.exe。而系统变量里将这俩都引用了编译的时候不知道用哪个了导致出错。所以要删掉一个。一个在C:\Windows\Microsoft.NET\Framework\v4.0.30319\cvtres.exe另一个在你安装VS的软件目录..\Microsoft Visual Studio 10.0\vc\bin\cvtres.exe然后右键属性--详细信息 查看两者版本号把老的Kill掉就完了。编译时_RTC_Shutdown和_RTC_InitBase相关错误的解决方法error LNK2001: 无法解析的外部符号 _RTC_Shutdown;error LNK2001: 无法解析的外部符号 _RTC_InitBase右键点击项目修改属性 配置属性 C/C 代码生成 基本运行时检查将值从“两者(......)”改为“默认值”。LINK : error LNK2001: 无法解析的外部符号 mainCRTStartup其它错误error LNK2019: 无法解析的外部符号 __imp_system该符号在函数 main 中被引用原因是system(pause);没有include编译选项, 需要手动指定Python 的include 路径 和链接接路径。代码:g Python.cpp -o Python-I/usr/include/python2.5 -L/usr/lib/python2.5-lpython2.5调用Python函数时参数的传递就是c的类型怎么转换成Python的类型另外一个问题是Python函数的返回值怎么转换成C中的类型。在C程序中用Python脚本传递参数或者获得Python脚本的返回值则要使用更多的函数来编写C程序。由于Python有自己的数据类型因此在C程序中要使用专门的API对相应的数据类型进行操作。1数字与字符串处理在Python/C API中提供了Py_BuildValue()函数对数字和字符串进行转换处理使之变成Python中相应的数据类型。其函数原型如下所示。PyObject* Py_BuildValue( const char *format, ...)其参数含义如下。· format格式化字符串如表8-1所示。Py_BuildValue()函数中剩余的参数即要转换的C语言中的整型、浮点型或者字符串等。其返回值为PyObject型的指针。在C语言中所有的Python类型都被声明为PyObject型。2列表操作在Python/C API中提供了PyList_New()函数用以创建一个新的Python列表。PyList_New()函数的返回值为所创建的列表。其函数原型如下所示。PyObject* PyList_New( Py_ssize_t len)其参数含义如下。· len所创建列表的长度。当列表创建以后可以使用PyList_SetItem()函数向列表中添加项。其函数原型如下所示。int PyList_SetItem( PyObject *list, Py_ssize_t index, PyObject *item)其参数含义如下。· list要添加项的列表。· index所添加项的位置索引。· item所添加项的值。同样可以使用Python/C API中PyList_GetItem()函数来获取列表中某项的值。PyList_GetItem()函数返回项的值。其函数原型如下所示。PyObject* PyList_GetItem( PyObject *list, Py_ssize_t index)其参数含义如下。· list要进行操作的列表。· index项的位置索引。Python/C API中提供了与Python中列表操作相对应的函数。例如列表的append方法对应于PyList_Append()函数。列表的sort方法对应于PyList_Sort()函数。列表的reverse方法对应于PyList_Reverse()函数。其函数原型分别如下所示。int PyList_Append( PyObject *list, PyObject *item)int PyList_Sort( PyObject *list)int PyList_Reverse( PyObject *list)对于PyList_Append()函数其参数含义如下。· list要进行操作的列表。· item要参加的项。对于PyList_Sort()和PyList_Reverse()函数其参数含义相同。· list要进行操作的列表。3元组操作在Python/C API中提供了PyTuple_New()函数用以创建一个新的Python元组。PyTuple_New()函数返回所创建的元组。其函数原型如下所示。PyObject* PyTuple_New( Py_ssize_t len)其参数含义如下。· len所创建元组的长度。当元组创建以后可以使用PyTuple_SetItem()函数向元组中添加项。其函数原型如下所示。int PyTuple_SetItem( PyObject *p, Py_ssize_t pos, PyObject *o)其参数含义如下所示。· p所进行操作的元组。· pos所添加项的位置索引。· o所添加的项值。可以使用Python/C API中PyTuple_GetItem()函数来获取元组中某项的值。PyTuple_GetItem()函数返回项的值。其函数原型如下所示。PyObject* PyTuple_GetItem( PyObject *p, Py_ssize_t pos)其参数含义如下。· p要进行操作的元组。· pos项的位置索引。当元组创建以后可以使用_PyTuple_Resize()函数重新调整元组的大小。其函数原型如下所示。int _PyTuple_Resize( PyObject **p, Py_ssize_t newsize)其参数含义如下。· p指向要进行操作的元组的指针。· newsize新元组的大小。4字典操作在Python/C API中提供了PyDict_New()函数用以创建一个新的字典。PyDict_New()函数返回所创建的字典。其函数原型如下所示。PyObject* PyDict_New()当字典创建后可以使用PyDict_SetItem()函数和PyDict_SetItemString()函数向字典中添加项。其函数原型分别如下所示。int PyDict_SetItem( PyObject *p, PyObject *key, PyObject *val)int PyDict_SetItemString( PyObject *p, const char *key, PyObject *val)其参数含义如下。· p要进行操作的字典。· key添加项的关键字对于PyDict_SetItem()函数其为PyObject型对于PyDict_SetItemString()函数其为char型。· val添加项的值。使用Python/C API中的PyDict_GetItem()函数和PyDict_GetItemString()函数来获取字典中某项的值。它们都返回项的值。其函数原型分别如下所示。PyObject* PyDict_GetItem( PyObject *p, PyObject *key)PyObject* PyDict_GetItemString( PyObject *p, const char *key)其参数含义如下。· p要进行操作的字典。· key添加项的关键字对于PyDict_GetItem()函数其为PyObject型对于PyDict_GetItemString()函数其为char型。使用Python/C API中的PyDict_DelItem()函数和PyDict_DelItemString()函数可以删除字典中的某一项。其函数原型如下所示。int PyDict_DelItem( PyObject *p, PyObject *key)int PyDict_DelItemString( PyObject *p, char *key)其参数含义如下。· p要进行操作的字典。· key添加项的关键字对于PyDict_DelItem()函数其为PyObject型对于PyDict_DelItemString()函数其为char型。使用Python/C API中的PyDict_Next()函数可以对字典进行遍历。其函数原型如下所示。int PyDict_Next( PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)其参数含义如下。· p要进行遍历的字典。· ppos字典中项的位置应该被初始化为0。· pkey返回字典的关键字。· pvalue返回字典的值。在Python/C API中提供了与Python中字典操作相对应的函数。例如字典的item方法对应于PyDict_Items()函数。字典的keys方法对应于PyDict_Keys()函数。字典的values方法对应于PyDict_Values()函数。其函数原型分别如下所示。PyObject* PyDict_Items( PyObject *p)PyObject* PyDict_Keys( PyObject *p)PyObject* PyDict_Values( PyObject *p)其参数含义如下。· p要进行操作的字典。5释放资源Python使用引用计数机制对内存进行管理实现自动垃圾回收。在C/C中使用Python对象时应正确地处理引用计数否则容易导致内存泄漏。在Python/C API中提供了Py_CLEAR()、Py_DECREF()等宏来对引用计数进行操作。当使用Python/C API中的函数创建列表、元组、字典等后就在内存中生成了这些对象的引用计数。在对其完成操作后应该使用Py_CLEAR()、Py_DECREF()等宏来销毁这些对象。其原型分别如下所示。void Py_CLEAR( PyObject *o)void Py_DECREF( PyObject *o)其参数含义如下。· o要进行操作的对象。对于Py_CLEAR()其参数可以为NULL指针此时Py_CLEAR()不进行任何操作。而对于Py_DECREF()其参数不能为NULL指针否则将导致错误。6模块与函数使用Python/C API中的PyImport_Import()函数可以在C程序中导入Python模块。PyImport_Import()函数返回一个模块对象。其函数原型如下所示。PyObject* PyImport_Import( PyObject *name)其参数含义如下。· name要导入的模块名。使用Python/C API中的PyObject_CallObject()函数和PyObject_CallFunction()函数可以在C程序中调用Python中的函数。其参数原型分别如下所示。PyObject* PyObject_CallObject( PyObject *callable_object, PyObject *args)PyObject* PyObject_CallFunction( PyObject *callable, char *format, ...)对于PyObject_CallObject()函数其参数含义如下。· callable_object要调用的函数对象。· args元组形式的参数列表。对于PyObject_CallFunction()函数其参数含义如下。· callable_object要调用的函数对象。· format指定参数的类型。· ...向函数传递的参数。使用Python/C API中的PyModule_GetDict()函数可以获得Python模块中的函数列表。PyModule_GetDict()函数返回一个字典。字典中的关键字为函数名值为函数的调用地址。其函数原型如下所示。PyObject* PyModule_GetDict( PyObject *module)其参数含义如下。· module已导入的模块对象。8.2.3 在C中嵌入Python实例在VC 6.0中新建一个名为“EmbPython”的空“Win32 Console Application”工程。向其添加如下所示的“EmbPython.c”文件。程序输出如下所示。-在C中嵌入Python-使用Python中的sum函数求解下列数之和0 1 2 3 4Using Function sumThe result is: 10使用Python中的函数分割以下字符串:this is an example结果如下所示:thisisanexample按回车键退出程序PyObject* pArgsPyTuple_New(1); //有几个参数就是几PyTuple_SetItem(pArgs,0,Py_BuildValue(i,3)); //初始第一个参数数据类型是i就是int值是3返回值转换如PyArg_ParseTuple[PyArg_ParseTuple]“如果没有参数从python到C, 是正常的但是有参数就废了报错”。我尝试实现并找到答案。http://stackoverflow.com/questions/145270/calling-c-c-from-python1. 无参数 函数声明C可用函数2. 有参数 那么实用SWIG 也就是我们需要一个接口文件 即z.i file%#include z.hextern 函数名(参数1 参数2...);%SWIG在不同语言互相调用发挥很重要的作用。SWIG有一个外部工具叫SWIG是Simplified Wrapper and Interface Generator 的缩写。其作者为David Beazley同时也是Python Essential Referenc 一书的作者。这个工具可以根据特别注释过的C/C头文件生成能给PythonTcl 和Perl 使用的包装代码。使用SWIG 可以省去你写前面所说的样板代码的时间。你只要关心怎么用C/C解决你的实际问题就好了。你所要做的就是按SWIG 的格式编写文件其余的就都由SWIG 来完成。你可以通过下面的网址找到关于SWIG 的更多信息。http://swig.orgPyrex创建C/C扩展的一个很明显的坏处是你必须要写C/C代码。你能利用它们的优点但更重要的是你也会碰到它们的缺点。Pyrex 可以让你只取扩展的优点而完全没有后顾之忧。它是一种更偏向Python 的C 语言和Python 语言的混合语言。事实上Pyrex 的官方网站上就说“Pyrex 是具有C 数据类型的Python“。你只要用Pyrex 的语法写代码然后运行Pyrex 编译器去编译源代码。Pyrex会生成相应的C 代码这些代码可以被编译成普通的扩展。你可以在它的官方网站下载到Pyrexhttp://cosc.canterbury.ac.nz/~greg/python/PyrexPsycoPyrex 免去了我们再去写纯C 代码的麻烦。不过你要去学会它的那一套与众不同的语法。最后你的Pyrex 代码还是会被转成C 的代码。无论你用C/CC/C加上SWIG还是Pyrex都是因为你想要加快你的程序的速度。如果你可以在不改动你的Python 代码的同时又能获得速度的提升那该多好啊。Psyco 的理念与其它的方法截然不同。与其改成C 的代码为何不让你已有的Python 代码运行的更快一些呢Psyco 是一个just-in-time(JIT)编译器它能在运行时自动把字节码转为本地代码运行。所以你只要(在运行时)导入Psyco 模块然后告诉它要开始优化代码就可以了。而不用修改自己的代码。Psyco 也可以检查你代码各个部分的运行时间以找出瓶颈所在。你甚至可以打开日志功能来查看Psyco 在优化你的代码的时候都做了些什么。你可以访问以下网站获取更多的信息http://psyco.sf.net嵌入嵌入是Python 的另一功能。与把C 代码包装到Python 中的扩展相对的嵌入是把Python 解释器包装到C 的程序中。这样做可以给大型的单一的要求严格的私有的并且(或者)极其重要的应用程序内嵌Python 解释器的能力。一旦内嵌了Python世界完全不一样了。Python 提供了很多官方文档供写扩展的人参考扩展与嵌入http://docs.python.org/extPython/C APIhttp://docs.python.org/api分发Python 模块http://docs.python.org/dist[python核心编程2e.d. - 扩展Python]