当前位置:首页 > > 充电吧
[导读]环境VS2005Python2.5.4 Windows XP SP3 简述一般开发过游戏的都知道Lua和C++可以很好的结合在一起,取长补短,把Lua脚本当成类似动态链接库来使用,很好的利用了脚本开发

环境

VS2005Python2.5.4 Windows XP SP3

 

简述

一般开发过游戏的都知道Lua和C++可以很好的结合在一起,取长补短,把Lua脚本当成类似动态链接库来使用,很好的利用了脚本开发的灵活性。而作为一门流行的通用型脚本语言python,也是可以做到的。在一个C++应用程序中,我们可以用一组插件来实现一些具有统一接口的功能,一般插件都是使用动态链接库实现,如果插件的变化比较频繁,我们可以使用Python来代替动态链接库形式的插件(堪称文本形式的动态链接库),这样可以方便地根据需求的变化改写脚本代码,而不是必须重新编译链接二进制的动态链接库。灵活性大大的提高了。

 

Python/CAPI简介

通过C++调用Python脚本主要要用到如下的一些Python提供的API,因为实际上C++要调用的是Python的解释器,而Python解释器本质就是实现在动态链接库里面的,因此在调用前和调用后要进行一些初始化和资源释放的工作,另外,要调用Python脚本里面的函数等等东西,需要Python提供的一些特殊API来包装C++调用。(可以参考[2])。

 

void Py_Initialize(void)

初始化Python解释器,如果初始化失败,继续下面的调用会出现各种错误,可惜的是此函数没有返回值来判断是否初始化成功,如果失败会导致致命错误。

 

int Py_IsInitialized(void)

检查是否已经进行了初始化,如果返回0,表示没有进行过初始化。

 

void Py_Finalize()

反初始化Python解释器,包括子解释器,调用此函数同时会释放Python解释器所占用的资源。

 

int PyRun_SimpleString(const char *command)

实际上是一个宏,执行一段Python代码。

 

PyObject* PyImport_ImportModule(char *name)

导入一个Python模块,参数name可以是*.py文件的文件名。类似Python内建函数import。

 

PyObject* PyModule_GetDict( PyObject *module)

相当于Python模块对象的__dict__属性,得到模块名称空间下的字典对象。

 

PyObject* PyRun_String(const char* str, int start,PyObject* globals, PyObject* locals)

执行一段Python代码。

 

int PyArg_Parse(PyObject* args, char* format, ...)

把Python数据类型解析为C的类型,这样C程序中才可以使用Python里面的数据。

 

PyObject* PyObject_GetAttrString(PyObject *o, char*attr_name)

返回模块对象o中的attr_name 属性或函数,相当于Python中表达式语句,o.attr_name。

 

PyObject* Py_BuildValue(char* format, ...)

和PyArg_Parse刚好相反,构建一个参数列表,把C类型转换为Python对象,使得Python里面可以使用C类型数据。

 

PyObject* PyEval_CallObject(PyObject* pfunc, PyObject*pargs)

此函数有两个参数,而且都是Python对象指针,其中pfunc是要调用的Python 函数,一般说来可以使用PyObject_GetAttrString()获得,pargs是函数的参数列表,通常是使用Py_BuildValue()来构建。

 

更多的API请参考官方的文档,比较直观简单,譬如怎样初始化一个类实例,怎样调用类成员函数。下面上点代码,感受下这个过程。

 

C++代码

#include "stdafx.h"

#include "Python.h"

 

int _tmain(int argc, _TCHAR* argv[])

{

       int nRet = -1;

 

       PyObject* pName = NULL;

       PyObject* pModule =NULL;

       PyObject* pDict = NULL;

       PyObject* pFunc = NULL;

       PyObject* pArgs = NULL;

       PyObject* pRet = NULL;

       do

       {

              // 初始化Python

              // 在使用Python系统前,必须使用Py_Initialize对其

              // 进行初始化。它会载入Python的内建模块并添加系统路

              // 径到模块搜索路径中。这个函数没有返回值,检查系统

              // 是否初始化成功需要使用Py_IsInitialized。

              Py_Initialize();

 

              // 检查初始化是否成功

              if (!Py_IsInitialized())

              {

                     break;

              }

 

              // 添加当前路径

              // 把输入的字符串作为Python代码直接运行,返回

              // 表示成功,-1表示有错。大多时候错误都是因为字符串

              // 中有语法错误。

              PyRun_SimpleString("importsys");

              PyRun_SimpleString("sys.path.append('./')");

 

              // 载入名为PyPlugin的脚本

              pName = PyString_FromString("PyPlugin");

              pModule = PyImport_Import(pName);

              if (!pModule)

              {

                     printf("can't findPyPlugin.pyn");

                     break;

              }

 

              pDict = PyModule_GetDict(pModule);

              if (!pDict)

              {

                     break;

              }

 

              // 找出函数名为AddMult的函数

              pFunc = PyDict_GetItemString(pDict, "AddMult");

              if (!pFunc || !PyCallable_Check(pFunc))

              {

                     printf("can't findfunction [AddMult]n");

                     break;

              }

 

              pArgs = Py_BuildValue("ii", 12, 14);

              PyObject* pRet = PyEval_CallObject(pFunc,pArgs);

              int a = 0;

              int b = 0;

              if (pRet && PyArg_ParseTuple(pRet,"ii", &a,&b))

              {

                     printf("Function[AddMult] call successful a + b = %d, a * b = %dn", a, b);

                     nRet = 0;

              }

 

              if (pArgs)

                     Py_DECREF(pArgs);

              if (pFunc)

                     Py_DECREF(pFunc);

              // 找出函数名为HelloWorld的函数

              pFunc = PyDict_GetItemString(pDict, "HelloWorld");

              if (!pFunc || !PyCallable_Check(pFunc))

              {

                     printf("can't findfunction [HelloWorld]n");

                     break;

              }

              pArgs = Py_BuildValue("(s)", "magictong");

              PyEval_CallObject(pFunc,pArgs);

       } while (0);

      

       if (pRet)

              Py_DECREF(pRet);

       if (pArgs)

              Py_DECREF(pArgs);

       if (pFunc)

              Py_DECREF(pFunc);

       if (pDict)

              Py_DECREF(pDict);

       if (pModule)

              Py_DECREF(pModule);

       if (pName)

              Py_DECREF(pName);

       Py_Finalize();

 

       return 0;

}

 

Python代码

#!/usr/bin/python

import string

 

class CMyClass:

       def HelloWorld(self):

print 'HelloWorld'

 

class SecondClass:

       def invoke(self,obj):

obj.HelloWorld()

 

def HelloWorld(strName):

print "Hello ", strName

 

def Add(a, b, c):

return a + b + c

 

def AddMult(a, b):

"""

"""

print "in FunctionAddMult..."

print a

print b

return a + b, a * b

 

def StringToUpper(strSrc):

return string.upper(strSrc)

 

下面还有几个比较重要的问题需要解决,且听慢慢道来。

 

C++怎么向Python传递参数

C++向Python传参数是以元组(tuple)的方式传过去的,因此我们实际上就是构造一个合适的Python元组就可以了,要用到PyTuple_New,Py_BuildValue,PyTuple_SetItem等几个函数,其中Py_BuildValue可以有其它一些的替换函数。

PyObject* pyParams = PyTuple_New(2);

       PyObject* pyParams1= Py_BuildValue("i",5);

       PyObject* pyParams2= Py_BuildValue("i",6);

       PyTuple_SetItem(pyParams,0, pyParams1);

       PyTuple_SetItem(pyParams,1, pyParams2);

       pRet = PyEval_CallObject(pFunc, pyParams);

<p style="color:rgb(57,57,57);font-family:Ve

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭