文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>python 与c集成

python 与c集成

时间:2009-06-29  来源:cxhwudi

1. 首先就是在编译器中把python安装目录include/与libs/加入,对于这点我在vc6中可以,但是在dev c++中即使加入了编译也会出错,说找不到python头文件,这点比较郁闷,不过考虑到一般windows编程都用的是vc,所以并没有什么影响吧!!!

然后用#include 就可以把python的主头文件包含进来了。

但是在调试的时候,会出现说找不到python25_d.lib的链接错误,出现这个错误的原因是python_d.lib是库的调试后形式,当我们以debug模式编译工程时,python就用这个lib文件,但是这个文件是不可用的。对于这点,最快的办法就是强制要求python在任何情况下都是用非调试版本,就可以了。要做到这一点

a) 在python目录include文件夹下,打开pyconfig.h,找到如下语句

# ifdef _DEBUG

# pragma comment(lib,"python25_d.lib")

# else

# pragma comment(lib,"python25.lib")

# endif /* _DEBUG */

将python25_d.lib改成python25.lib

b) 找到

#ifdef _DEBUG

# define Py_DEBUG

#endif

将其用/**/屏蔽

这样就可以了。

2. Python初始化
python的初始化很简单我们只需在程序开始时调用Py_Initialize(),结束的时候调用Py_Finalize()就可以了

3. PyObject
在c语言程序中,我们使用PyObject来操纵python对象,一个PyObejct就是一个结构体,他表示某个与python相关的数据。只不过我们处理的都是该对象的指针。

PyObject *t; //t is a pointer to the python object

4. Reference counting
对于python,跟directx比较类似,都采用了一种引用计数的机制,我们不需要自己去释放python对象,只需减少它的引用计数就可以了,当计数为0时,系统自己会安全释放。

对于减少引用计数,我们使用Py_XDECREF(),而增加引用计数则是由代码负责完成。

5. 载入脚本
我们首先写一个python脚本,命名为test.py

printf “Hello World”

然后我们在主程序中调用,如下

PyObject *pName = PyString_FromString("test");

PyObject * pModule = PyImport_Import(pName);

if(!pModule)

{

printf("could not open script \n");

return 0;

}

这样就可以在控制台上面看见Hello World了。

6. 调用脚本定义函数
我们在test.py中定义一个函数,

def GetMax(X, Y):

print "\tGet Max was called from the host with",X,"and",Y

if X > Y:

return X

else:

return Y

对于python,它提供了一个模块词典的概念,一个模块词典就是一个数据结构,负责将脚本中的标识符分别映射到与它们对应的代码或是数据上,如果在c程序中我们要调用getMax函数,我们就需要用脚本词典去获得一个包含有函数GetMax的python对象。如下:

PyObject *pName = PyString_FromString("test");

PyObject * pModule = PyImport_Import(pName);

if(!pModule)

{

printf("could not open script \n");

return 0;

}

PyObject *pDict = PyModule_GetDict(pModule);

然后我们获得GetMax函数

PyObject *pFunc = PyDict_GetItemString(pDict, "GetMax");

在我们向该函数中传递两个参数,python使用是tuple结构来传递参数

PyObject *pParams = PyTuple_New(2);

PyObject *pCurrParam;

pCurrParam = PyInt_FromLong(16);

PyTuple_SetItem(pParams, 0, pCurrParam);

pCurrParam = PyInt_FromLong(32);

PyTuple_SetItem(pParams, 1, pCurrParam);

我们向GetMax函数传递了16与32,然后就要调用函数并输出返回值了,如下

PyObject *pMax = PyObject_CallObject(pFunc, pParams);

int max = PyInt_AsLong(pMax);

这样max就为32了

7. Python调用c语言函数

同样我们可以用python调用c语言函数,这样就能做到真正的交互了。首先定义一个c语言函数。

PyObject * RepeatString (PyObject *pSelf, PyObject *pParams)

{

printf("\tRepeatString was called from:\n");

char *pstrString;

int iRepCount;

if(!PyArg_ParseTuple(pParams, "si", &pstrString, &iRepCount))

{

printf("uable to parse parameter tuple.\n");

exit(0);

}

for (int i = 0; i < iRepCount; i++)

{

printf("\t\t%d: %s \n", i, pstrString);

}

return PyInt_FromLong(iRepCount);

}

该函数接受两个参数,pSelf没有什么用处,而另一个pParams则是用来传递参数的。由于传递参数都是用tuple结构,我们就使用PyArg_ParseTuple这个函数,对于”si”,表示的是按照字符串与整数来读取参数。

然后我们在主应用程序中定义一个api来存放该函数

PyMethodDef HostAPIFuncs [] =

{

{"RepeatString", RepeatString, METH_VARARGS, NULL},

{NULL, NULL, NULL, NULL}

};

对于这个数组的最后一行NULL来说,表明该数组结束。

接下来我们创建一个module,用来供脚本调用

if (!PyImport_AddModule("HostAPI"))

{

printf("Host API module could not be created");

}

然后将我们定义的函数表加入这个模块

if (!Py_InitModule("HostAPI", HostAPIFuncs))

{

printf("Host API module could not be initialized");

}

创建一个python脚本test.py,然后在第一行写上

import HostAPI

再定义一个函数用来调用HostAPI函数

def PrintStuff():

RepCount = HostAPI.RepeatString("String repetition", 4)

最后我们再在主程序中调用PrintStuff函数,就可以了

总体程序如下:

//create a module

if (!PyImport_AddModule("HostAPI"))

{

printf("Host API module could not be created");

}

//create a function table

PyMethodDef HostAPIFuncs [] =

{

{"RepeatString", RepeatString, METH_VARARGS, NULL},

{NULL, NULL, NULL, NULL}

};

//initial the module with the function table

if (!Py_InitModule("HostAPI", HostAPIFuncs))

{

printf("Host API module could not be initialized");

}

//load a python script

PyObject *pName = PyString_FromString("test");

PyObject * pModule = PyImport_Import(pName);

if(!pModule)

{

printf("could not open script \n");

return 0;

}

//get the module dict

PyObject * pDict = PyModule_GetDict ( pModule );

//get the function with the dict

PyObject * pFunc = PyDict_GetItemString ( pDict, "PrintStuff" );

//call the function

PyObject_CallObject ( pFunc, NULL );

Py_XDECREF ( pFunc );

Py_XDECREF ( pDict );

Py_XDECREF(pModule);

Py_XDECREF(pName);

这样就完成了python与c的集成,不过这只是一些简单的应用,具体还是要参考python manual。(以上代码来自于《游戏脚本高级编程》)
相关阅读 更多 +
排行榜 更多 +
找茬脑洞的世界安卓版

找茬脑洞的世界安卓版

休闲益智 下载
滑板英雄跑酷2手游

滑板英雄跑酷2手游

休闲益智 下载
披萨对对看下载

披萨对对看下载

休闲益智 下载