Python嵌入C++(2)

本文介绍了在C++中调用Python模块的方法,包括导入模块、获取调用对象、调用函数等步骤。针对无参数、有参数(无返回值、有返回值)及多参数函数分别给出调用示例,并列出相关函数原型,还提到Python先天支持GP。

Python嵌入C++(2)
                               在C++中调用python模块。

要在C++中调用python模块,事实上比较复杂,总结如下:
(1)导入要调用函数所在的模块。
(2)在相应的模块中获取要调用的对象。
(3)调用相应的函数。

对于第三步,根据模块中的函数是无参数还是有参数,又可分别对待。对于无参数的函数,上面的三步即可满足要求,但对于有参数的函数,还得扩展上面的第三步,总结如下:
(1)导入要调用函数所在的模块。
(2)在相应的模块中获取要调用的对象。
(3)把要作为参数提供给Python模块的所有C++变量建立参数对象。
(4)调用相应的函数,并为之提供相应的参数。
(5)如果函数有返回值,把返回的值转换为C++变量。

对上面的无参数函数模块的调用示例如下:

(以下示例均在VS.NET 2003及Dev-C++4.9.9.0下面调试通过.)
#include "python.h"

int main(int argc,char** argv)
{
 Py_Initialize();
 
 PyObject *myMod = NULL,
   *myFunc = NULL;

 myMod = PyImport_ImportModule("PythonInC"); //First step.
 myFunc = PyObject_GetAttrString(myMod,"Hello");//Second step.
 PyEval_CallObject(myFunc,NULL);   //Third step.
 
 Py_Finalize();

 return (1);
}
其中的模块定义如下:
#Test for mudule nest in C++.
def Hello():
 print "Hello,world"
下面给出上面示例中用到的函数原型。
PyObject* PyImport ImportModule(char *name)
Return value: New reference.
This is a simplified interface to PyImport ImportModuleEx() below, leaving the globals and locals
arguments set to NULL. When the name argument contains a dot (when it specifies a submodule of a
package), the fromlist argument is set to the list ['*'] so that the return value is the named module
rather than the top-level package containing it as would otherwise be the case. (Unfortunately,
this has an additional side effect when name in fact specifies a subpackage instead of a submodule:
the submodules specified in the package's all variable are loaded.) Return a new reference
to the imported module, or NULL with an exception set on failure (the module may still be created
in this case | examine sys.modules to find out).

PyObject* PyObject GetAttrString(PyObject *o, char *attr name)
Return value: New reference.
Retrieve an attribute named attr name from object o. Returns the attribute value on success, or
NULL on failure. This is the equivalent of the Python expression `o.attr name'.

下面再来个无返回值单参数的示例:
#include "python.h"
#include <cassert>

int main(int argc,char** argv)
{
 Py_Initialize();
 
 PyObject *myMod = NULL,
   *myFunc = NULL,
   *myArg = NULL;

 myMod = PyImport_ImportModule("PythonInC_1"); //First step.

#ifndef NDEBUG
#define NDEBUG
 assert(PyObject_HasAttrString(myMod,"Hello");
#undef NDEBUG
#endif

 myFunc = PyObject_GetAttrString(myMod,"Hello");//Second step.

 myArg = Py_BuildValue("(s)","Bluejugar"); //Third step.

 PyEval_CallObject(myFunc,myArg);  //Fourth step.

 Py_Finalize();

 return (1);
}
模块定义为:
PythonInC_1.py:
#Test for single argument function calling.
def Hello(who):
 print 'Hello,',who,'!'
新增加函数的原型:
PyObject* Py BuildValue(char *format, ...)
Return value: New reference.
Create a new value based on a format string similar to those accepted by the PyArg Parse*()
family of functions and a sequence of values. Returns the value or NULL in the case of an error;
an exception will be raised if NULL is returned.

有返回值单参数的示例:
#include "python.h"
#include <cassert>
#include <iostream>

int main(int argc,char** argv)
{
 Py_Initialize();
 
 PyObject *myMod = NULL,
   *myFunc = NULL,
   *myArg = NULL,
   *myRet = NULL;

 myMod = PyImport_ImportModule("PythonInC_2");

#ifndef NDEBUG
#define NDEBUG
 assert(PyObject_HasAttrString(myMod,"Hello");
#undef NDEBUG
#endif

 myFunc = PyObject_GetAttrString(myMod,"Hello");

 myArg = Py_BuildValue("(s)","Bluejugar");

 myRet = PyEval_CallObject(myFunc,myArg);

 char* sRet = NULL;
 PyArg_Parse(myRet,"s",&sRet);

 std::cout<<sRet<<std::endl;

 Py_Finalize();

 return (1);
}
其中的模块重新定义为:
PythonInC_2.py:
#Test for single argument and return value.
def Hello(who):
 word = "Hello, " + who + "."
 return word

对于模块中的多参数函数,对其传入多个参数时,是传入将每个参数定义成一个对象传入,还是将它们各自定义成一个对象传入?我现在也不是很清楚该怎么做,有些例子上是使用了tuple.
示例如下:
#include "python.h"
#include <cassert>
#include <iostream>

int main(int argc,char** argv)
{
 Py_Initialize();
 
 PyObject *myMod = NULL,
   *myFunc = NULL,
   *myArgs = NULL,
   *myRet = NULL;

 myMod = PyImport_ImportModule("PythonInC_3");

#ifndef NDEBUG
#define NDEBUG
 assert(PyObject_HasAttrString(myMod,"Add");
#undef NDEBUG
#endif

 myFunc = PyObject_GetAttrString(myMod,"Add");

 myArgs = PyTuple_New(2);
 PyTuple_SetItem(myArgs,0,Py_BuildValue("i",2000) );
 PyTuple_SetItem(myArgs,1,Py_BuildValue("i",8) );

 myRet = PyEval_CallObject(myFunc,myArgs);

 int nRet = 0;

 PyArg_Parse(myRet,"i",&nRet);

 std::cout<<nRet<<std::endl;

 Py_Finalize();

 return (1);
}
模块定义:
PythonInC_3.py:
#Test for multi-arguments.
def Add(nA,nB):
 return (nA + nB)

突然发现动态语言(如Python)竟然先天支持GP(generic programming),很是感触。

附注:虽然开始说是像记日记一样把每日所得记下来,但后来发现如果真是这样,那还是只能写下一些行云流水般的东西,每隔几天,总结一下,再写下来,才算是有所悟,有所得啊.不过这篇文章本来早就写了,不料csdn的blog这几天老是出"运行时错误",听说用的是伪软的ASP.net.哎,看来,伪软的东西也是怎的不怎的啊.("怎"字拼成"za",念三声,"的"字拼成"di",念四声.)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值