dede网站后台地址扫描,网站设计公司建设,cms系统表单,wordpress virtueFrom: http://www.flatws.cn/article/program/c/2010-08-24/9677.html Python代码在实现某些功能的时候非常方便#xff0c;如果能够将Python代码与C程序结合起来#xff0c;那么一定会使Problem Solving方便许多#xff08;比如#xff0c;游戏脚本系统#xff09;~ 从学…From: http://www.flatws.cn/article/program/c/2010-08-24/9677.html Python代码在实现某些功能的时候非常方便如果能够将Python代码与C程序结合起来那么一定会使Problem Solving方便许多比如游戏脚本系统~ 从学完Python开始就一直想研究一下C内嵌Python是怎么回事可是每次都坚持不下来。。。今天上校内偶然间看到同学求助怎么实现输入表达式输出结果~我想到了Python的builtin函数eval正好借这个机会研究一下怎么实现C调用Python函数 假定您的系统中已经安装了Python我使用的版本是2.6~ 1.配置IDE。 我用的是VS2008只需要将Python安装路径下的include文件夹和libs文件夹添加到C目录中即可。步骤是Tools - Options - Project Solution - VC Dir选择右上的Dropdown List分别将include文件夹和libs文件夹添加到include和lib项中。 2.编写Python脚本。 为了完成自动计算值的功能我写了如下的脚本文件名是python_code.py def calculate(expression):try: result eval(expression) except:print Eval error!return Nonereturn result将这个文件与C程序文件放到同一目录下这样保证编译器可以根据相对路径找到。3.Python嵌入的方式 - 高级vs低级 接下来进入C内嵌Python函数的关键部分了。根据官方的帮助文档有两个类型的Python调用High Level与Low Level。High Level就是调用者不需要管理与Python相关的内存只有3行代码即可分别是Py_Initialize()来初始化解释器注意此时程序仍然是由C的编译器进行编译调用PyRun_SimpleString()其中参数是要执行的Python代码如果是一个确定的Python文件那么我们可以调用PyRun_SimpleFile()直接执行Python文件。最后调用Py_Finalize()方法结束解释器工作。 使用High Level对程序员的要求非常少基本就是会写Python代码就会在C中调用Python的方法但是弊端就是当前程序不能与Python的方法进行数据的交互所以局限性非常大。 所以如果我们需要与Python程序进行交互比如计算表达式的值我们只能使用低级的方法了。 4.Low Level程序编写步骤。 说实话以前几次当我想学习Python内嵌的时候都是因为看到为了进行Low Level调用而编写的冗长的C代码实在是太恐怖了。。可是今天静下来看一看其实只有4步 1导入要用到的模块 要导入模块其实很简单首先我们需要提供模块的文件名注意跟Python中导入模块一样这里的文件名不能包含.py后缀比如我的文件名是python_code.py我在程序中只需要提供python_code这个字符串就可以了。这一部分代码如下注意使用到的两个函数PyString_FromString和PyImport_Import PyObject *pyFileName PyString_FromString(filename.c_str());
PyObject *pyMod PyImport_Import(pyFileName); // load the module注意在C中一切Python的object都是用PyObject*来代替。第一行语句将C中的char数组转化为Python中的字符串然后利用这个文件名导入模块请注意函数是PyImport_Import而不是别的。好了模块导入之后我们需要验证模块导入是否成功如果成功我们就可以进行第二步了找到我们要调用的方法。 2找到要调用的方法。 基本原理是这样的在C中如果我们有了模块就可以获得模块对应的attr列表dir(模块名)然后我们就可以利用我们所需要的方法名找到我们所需要的那个attr。找到之后我们要判断时候找到成功而且是否是可以调用的callable。这部分代码如下 // load the function
PyObject *pyFunc PyObject_GetAttrString(pyMod, methodname.c_str());
if(pyFunc PyCallable_Check(pyFunc))
{// talk later!!!
} 第一句话首先利用PyObject_GetAttrString找到我们所需的“方法”对象然后检测对象时候有效是否是Callable的如果这两者检测都成功了那么ok进入下一步。3构造参数。 方法有了接下来就缺参数了。参数是以tuple的形式传递给方法的所以我们需要一个PyObject*对象来充当一个Tuple利用PyTuple_New方法即可。这个方法的参数是tuple内元素的个数我认为可以理解为参数的个数。由于我的Python代码只有一个参数所以这里我直接给1其他情况可以根据参数的数量赋值。 然后解释构建参数了根据参数的不用类型可以调用不同的方法。这里由于我在C程序中的参数是字符串在Python中的参数也是一个字符串所以我使用PyString_FromString方法其中Py是前缀第一个String指的是在Python代码中我们需要一个String也就是目的参数类型而FromString顾名思义就是C中参数的类型。这个方法接受一个参数也就是一个string注意这个string其实是char型数组。返回的结果是一个PyObject*。 最后一步是要把构造的参数赋值给我们的Tuple用PyTuple_SetItem方法就可以了。第一个参数是指向Tuple的PyObject指针第二个参数是value在Tuple中的位置参数从0开始最后一个就是咱们的value了这部分代码如下 PyObject *pyParams PyTuple_New(1);
PyObject *pyValue PyString_FromString(expression.c_str());
PyTuple_SetItem(pyParams, 0, pyValue);4调用方法取返回值。好了大功即将告成~最后一步当然是调用方法了利用PyObject_CallObject方法第一个参数是指向函数的那个PyObject指针第二个参数则是指向我们Tuple的那个PyObject指针。返回值仍然是PyObject指针对象。我们需要对它进行解析将它转换成C的类型。这部分代码如下 // ok, call the function
pyValue PyObject_CallObject(pyFunc, pyParams);
if(pyValue)
{*result PyFloat_AsDouble(pyValue); // result is a double varreturn true;
} 好了到这里调用的全部过程就完成了其实还不赖。最后为了方便大家理解我把整个代码贴了上来。特别说明如果您是用Python安装包的形式安装的Python那么这个程序只能以Release方式运行原因是安装包版Python在libs文件夹下只有Release版的lib文件而debug模式需要Python26_d.lib也就是debug模式的。如果您在运行时提示无法打开python26_d.lib文件那么请换成Release模式或者下载Python源码自己编译这样就会生成_d的lib文件了 由于我的水平实在有限文中难免有错误希望各位看到之后留言指正谢谢各位
#include Python.h // this is in python-install-path
#include conio.h
#include iostream
#include stringusing namespace std;bool calc(string filename, string methodname, string expression, double *result)
{PyObject *pyFileName PyString_FromString(filename.c_str());PyObject *pyMod PyImport_Import(pyFileName); // load the moduleif (pyMod) // if ok{PyObject *pyFunc PyObject_GetAttrString(pyMod, methodname.c_str()); // load the functionif (pyFunc PyCallable_Check(pyFunc)){PyObject *pyParams PyTuple_New(1);PyObject *pyValue PyString_FromString(expression.c_str());PyTuple_SetItem(pyParams, 0, pyValue);pyValue PyObject_CallObject(pyFunc, pyParams); // ok, call the functionif (pyValue){*result PyFloat_AsDouble(pyValue);return true;}else{return false;}}else{return false;}}else{return false;}return false;
}int main(void)
{string filename python_code; // filename is settled!string methodname calculate; // method name is also settled!string expression ; // get user input!double result 0.0;printf(\nPlease input the expression: );getline(cin, expression);// first initPy_Initialize();if (calc(filename, methodname, expression, result)){printf(\nResult is : %lf\n, result);}else{printf(\nError occurred...\n);}// last fini!Py_Finalize();getch();return 0;
}