C++嵌入Python程序(二):参数传入及返回

在开始编写程序之前,我们需对下面以下几个常用参数处理函数有个大概的了解:

1)         Py_BuildValue()函数

作用:将C/C++类型类型的数据转变成PyObject*对象。

原型:PyAPI_FUNC(PyObject*) Py_BuildValue(const char *format, ...);(VC中复制过来的),有点类似与printf(format,…).

参数解释:format及转换格式,类似与C语言中%d,%f,后面的不定参数对应前面的格式,具体格式如下

         "s"(string) [char *] :将C字符串转换成Python对象,如果C字符串为空,返回NONE。

         "s#"(string) [char *, int] :将C字符串和它的长度转换成Python对象,如果C字符串为空指针,长度忽略,返回NONE。

         "z"(string or None) [char *] :作用同"s"。

      "z#" (stringor None) [char *, int] :作用同"s#"。

      "i"(integer) [int] :将一个C类型的int转换成Python int对象。

         "b"(integer) [char] :作用同"i"。

         "h"(integer) [short int] :作用同"i"。

         "l"(integer) [long int] :将C类型的long转换成Pyhon中的int对象。

         "c"(string of length 1) [char] :将C类型的char转换成长度为1的Python字符串对象。

         "d"(float) [double] :将C类型的double转换成python中的浮点型对象。

         "f"(float) [float] :作用同"d"。

         "O&"(object) [converter, anything] :将任何数据类型通过转换函数转换成Python对象,这些数据作为转换函数的参数被调用并且返回一个新的Python对象,如果发生错误返回NULL。

         "(items)"(tuple) [matching-items] :将一系列的C值转换成Python元组。

         "[items]"(list) [matching-items] :将一系列的C值转换成Python列表。

         "{items}"(dictionary) [matching-items] :将一系类的C值转换成Python的字典,每一对连续的C值将转换成一个键值对。

举例

         后面为PyObject的返回值

Py_BuildValue("")None

         Py_BuildValue("i",123) 123

         Py_BuildValue("iii",123, 456, 789) (123, 456, 789)

         Py_BuildValue("s","hello") 'hello'

         Py_BuildValue("ss","hello", "world") ('hello', 'world')

         Py_BuildValue("s#","hello", 4) 'hell'

         Py_BuildValue("()")()

         Py_BuildValue("(i)",123) (123,)      

         Py_BuildValue("(ii)",123, 456) (123, 456)

         Py_BuildValue("(i,i)",123, 456) (123, 456)

         Py_BuildValue("[i,i]",123, 456) [123, 456]      Py_BuildValue("{s:i,s:i}", "abc",123, "def", 456) {'abc': 123, 'def': 456}

         Py_BuildValue("((ii)(ii))(ii)", 1, 2, 3, 4, 5, 6) (((1, 2), (3, 4)), (5, 6))

2)         PyArg_ParseTuple函数

作用:此函数其实相当于sscanf(str,format,…),是Py_BuildValue的逆过程,这个函数将PyObject参数转换成C/C++数据类型,传递的是指针,但这个函数与Py_BuildValue有点不同,这个函数只能解析Tuple元组,而Py_BuildValue函数可以生成元组,列表,字典等。

原型:PyAPI_FUNC(int) PyArg_ParseTuple(PyObject *args, const char *format,...)

Args:一般为Python程序返回的元组。

Foramt:与Py_BulidValue类型,就不在累述咯。

3)         元组操作函数:

因为程序之间传递的参数,大多数为Tuple类型,所以有专门的函数来操作元组:

PyAPI_FUNC(PyObject *)PyTuple_New(Py_ssize_t size);

解释:新建一个参数列表(调试了下,发现其实是用链表实现的),size列表为长度的宽度

PyAPI_FUNC(Py_ssize_t)PyTuple_Size(PyObject *);

解释:获取该列表的大小

PyAPI_FUNC(PyObject *)PyTuple_GetItem(PyObject *, Py_ssize_t);

解释:获取该列表某位置的值

PyAPI_FUNC(int) PyTuple_SetItem(PyObject *,Py_ssize_t, PyObject *);

解释:设置该列表此位置的值。如PyTuple_SetItem(pyParams,1,Py_BuildValue("i",2));设置第2个位置的值为2的整数。

备注:对应的列表和字典也有对应的操作,详细见例子:

例子A:一个字符串参数和两个整数参数的例子

Demo.py的内容:

  1. def Hello(s):
  2. print( "helloWord")
  3. print(s)
  4. def Add(a,b):
  5. print( "{0}".format(a+b))

C++文件的内容:

  1. #include<Python27/python.h>
  2. int main()
  3. {
  4. Py_Initialize();
  5. if(!Py_IsInitialized())
  6. {
  7. printf( "PythonInit failed!\n");
  8. return0;
  9. }
  10. PyObject*pModule = NULL;
  11. PyObject*pFunc = NULL;
  12. PyObject*pArg = NULL;
  13. pModule= PyImport_ImportModule( "Demo");
  14. pFunc= PyObject_GetAttrString(pModule, "Hello");
  15. pArg= Py_BuildValue( "(s)", "function with arguement"); //一个字符串参数
  16. PyEval_CallObject(pFunc,pArg);
  17. pFunc= PyObject_GetAttrString(pModule, "Add"); //两个整形的参数
  18. pArg= Py_BuildValue( "(i,i)", 10, 25);
  19. PyEval_CallObject(pFunc,pArg);
  20. Py_Finalize();
  21. Return0;
  22. }

输出的结果为:


例子B:元组操作参数的例子

Demo.py的内容:

  1. def Add(a,b):
  2. print( "{0}".format(a+b))

C++文件的内容:

  1. #include<Python27/python.h>
  2. int main()
  3. {
  4. Py_Initialize();
  5. if(!Py_IsInitialized())
  6. {
  7. printf( "PythonInit failed!\n");
  8. return0;
  9. }
  10. PyObject*pModule = NULL;
  11. PyObject*pFunc = NULL;
  12. PyObject*pArg = NULL;
  13. pModule= PyImport_ImportModule( "Demo");
  14. pFunc= PyObject_GetAttrString(pModule, "Add"); //两个整形的参数
  15. pArg= PyTuple_New( 2); //确定Add函数两个参数
  16. PyTuple_SetItem(pArg, 0,Py_BuildValue( "i", 2)); //对参赛元组复制
  17. PyTuple_SetItem(pArg, 1,Py_BuildValue( "i", 3));
  18. PyEval_CallObject(pFunc,pArg);
  19. Py_Finalize();
  20. Return0;
  21. }

运行结果:


例子C:列表操作参数的例子

Demo.py的内容:

  1. def printList(l):
  2. print len(l)
  3. for var in l:
  4. print var

C++文件的内容:

  1. #include<Python27/python.h>
  2. int main()
  3. {
  4. Py_Initialize();
  5. if(!Py_IsInitialized())
  6. return0;
  7. PyObject*pModule = PyImport_ImportModule( "Demo");
  8. PyObject*pyFunc_printList = PyObject_GetAttrString(pModule, "printList");
  9. if(pModule&& PyCallable_Check(pyFunc_printList))
  10. {
  11. PyObject*pyParams = PyList_New( 0); //初始化一个列表
  12. PyList_Append(pyParams,Py_BuildValue( "i", 5)); //列表添加元素值
  13. PyList_Append(pyParams,Py_BuildValue( "i", 2));
  14. PyList_Append(pyParams,Py_BuildValue( "i", 6));
  15. PyList_Append(pyParams,Py_BuildValue( "i", 8));
  16. PyObject*args = PyTuple_New( 1); <span style= "background-color: rgb(255, 102, 102);"> //这步很关键:将列表转换成元组的一个元素后传递给Python程序</span>
  17. PyTuple_SetItem(args, 0,pyParams);
  18. PyEval_CallObject(pyFunc_printList,args);
  19. }
  20. Py_Finalize();
  21. Return0;
  22. }

运行结果:


例子D:传递类参数的例子

Demo.py的内容:

  1. class Person:
  2. def __init__(self, name):
  3. self.name = name
  4. def printName(self):
  5. print self.name

C++文件的内容:

  1. #include<Python27/python.h>
  2. int main()
  3. {
  4. Py_Initialize();
  5. if(!Py_IsInitialized())
  6. return0;
  7. PyObject*pModule = NULL;
  8. PyObject*pFunc = NULL;
  9. PyObject*pArg = NULL;
  10. PyObject*pClass = NULL;
  11. PyObject*pObject = NULL;
  12. pModule= PyImport_ImportModule( "Demo");
  13. pClass= PyObject_GetAttrString(pModule, "Person"); //先获取类名
  14. pArg= PyTuple_New( 1);
  15. PyTuple_SetItem(pArg, 0,Py_BuildValue( "s", "Jacky"));
  16. pObject=PyEval_CallObject(pClass,pArg); //根据类名实例化对象
  17. pFunc= PyObject_GetAttrString(pObject, "printName"); //根据对象得到成员函数
  18. PyEval_CallObject(pFunc, NULL);
  19. Py_Finalize(); Return 0;
  20. }

运行结果:



例子E:Python程序返回参数的例子

Demo.py的内容:

  1. def mix(a,b):
  2. r1 = a + b
  3. r2 = a - b
  4. return (r1, r2)

C++文件的内容:

  1. #include<Python27/python.h>
  2. int main()
  3. {
  4. <span style= "white-space:pre"> </span>Py_Initialize();
  5. if(!Py_IsInitialized())
  6. return 0;
  7. PyObject *pModule = PyImport_ImportModule( "Demo");
  8. PyObject *pyFunc_mix = PyObject_GetAttrString(pModule, "mix");
  9. if(pModule && PyCallable_Check(pyFunc_mix))
  10. {
  11. PyObject *pyParams = PyTuple_New( 2);
  12. PyTuple_SetItem(pyParams, 0,Py_BuildValue( "i", 5));
  13. PyTuple_SetItem(pyParams, 1,Py_BuildValue( "i", 2));
  14. //PyTuple_SetItem(pyParams,2,Py_BuildValue("i",2));
  15. int r1 = 0, r2 = 0;
  16. PyObject *pyValue = PyObject_CallObject(pyFunc_mix,pyParams); //调用函数返回结果
  17. PyArg_ParseTuple(pyValue, "i|i",&r1,&r2); //分析返回的元组值
  18. if(pyValue)
  19. {
  20. printf( "%d %d\n",r1,r2);
  21. }
  22. }
  23. Py_Finalize();
  24. <span style= "white-space:pre"> </span> return 0;
  25. }

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值