最近参考了别人的C++调用python方法,我把它封装成了一个pyinit的工具类。这样可以使我们在主函数中,只需很少的几步就可以完成python的调用。
pyinit.h
#ifndef _PYINIT_H
#define _PYINIT_H
#include <Python.h>
typedef PyObject py_object; //这个替换是我的个人习惯,我很少用大写的
class pyinit {
public:
pyinit();
~pyinit();
public:
//执行一段python代码,就好像__main__函数中执行一样,默认是导入sys,和路径
void pyrun_simple_string(const char* s1 = "import sys",
const char* s2 = "sys.path.append('./')"); //执行一段python代码,就好像__main__函数中执行一样,默认是导入sys,和路径
void load_py_script(const char* name); //加载python脚本,获得name,module,dict
void find_function(const char* f); //查找要执行的函数
void set_item(const char* type); //设置参数
void call_function(); //调用函数
private:
pyinit(const pyinit& other);
pyinit& operator=(const pyinit& other);
private:
py_object* name_; //文件名
py_object* module_; //模块
py_object* dict_; //想到与Python模块对象的_dict_属性,得到模块名称空间下的字典对象
py_object* func_; //要执行的函数
py_object* args_; //参数
};
pyinit.cpp
#include "pyinit.h"
pyinit::pyinit()
: name_(NULL),
module_(NULL),
dict_(NULL),
func_(NULL),
args_(NULL) //由于都是指针,所以初值全部赋空
{
Py_Initialize(); //初始化,无返回值
assert(Py_IsInitialized()); //靠着这来判断是否初始化成功
}
pyinit::~pyinit()
{
Py_DECREF(name_); //减少引用计数
Py_DECREF(args_);
Py_DECREF(module_);
Py_Finalize(); //销毁
name_ = NULL;
module_ = NULL;
dict_ = NULL;
func_ = NULL;
args_ = NULL;
}
void pyinit::pyrun_simple_string(const char* s1, const char* s2) //执行s1,s2,如improt sys
{
PyRun_SimpleString(s1);
PyRun_SimpleString(s2);
}
void pyinit::load_py_script(const char* name) //执行脚本,得到名字,模块,字典属性
{
assert(name != NULL);
name_ = PyString_FromString(name);
module_ = PyImport_Import(name_);
assert(module_ != NULL);
dict_ = PyModule_GetDict(module_);
assert(dict_ != NULL);
}
void pyinit::find_function(const char* f) //查找函数,f是函数名
{
assert(f != NULL);
func_ = PyDict_GetItemString(dict_, f);
assert(func_ != NULL);
assert(PyCallable_Check(func_)); //检查函数是否可调
}
void pyinit::set_item(const char* name) //设置参数
{
assert(name != NULL);
args_ = PyTuple_New(1); //一个参数就new一个元组
PyTuple_SetItem(args_, 0, Py_BuildValue("s", name)); //args_是一个元组参数,
}
void pyinit::call_function() //调用函数
{
PyObject_CallObject(func_, args_);
}
测试文件:
测试文件使用用来解析xml的,形式已经给出。
#include "pyinit.h"
#include <iostream>
int main()
{
pyinit py;
py.pyrun_simple_string();
py.load_py_script("resolver");
py.find_function("Parse_XML");
py.set_item("movies.xml");
py.call_function();
return 0;
}