使用C++调用python3
正常使用流程
- 第一步:包含头文件
#include <python3.6m/Python.h>
- 第二步: 初始化Python解释器
Py_Initialize();
- 第三步:设置要调用的python文件路径
PyRun_SimpleString("import sys");//执行import语句
PyRun_SimpleString("sys.path.append('/home/xx/src')");
- 第四步:加载xx.py文件,注意不要加上后缀
pModule = PyImport_ImportModule("xx");//xx.py
if(pModule == NULL)
{
PyErr_Print();
return;
}
- 第五步:加载python中定义initRobot函数
PyObject * pInitRobot = PyObject_GetAttrString(pModule,"initRobot");
if(pInitRobot == NULL)
{
PyErr_Print();
return;
}
- 第六步:执行python中定义initRobot函数,无参直接可以PyObject_CallObject的第二个参数可以写为nullptr
PyObject_CallObject(pInitRobot, nullptr);
- 第七步:释放声明的PyObject,及释放解析器
Py_DECREF(pInitRobot);
Py_DECREF(pModule);
Py_Finalize();
需要传入参数到python
- 需要传入python的参数为list的
PyObject *PyList = PyList_New(7);//定义一个与数组等长的PyList对象数组
PyObject *ArgList = PyTuple_New(1);//定义一个Tuple对象,Tuple对象的长度与Python函数参数个数一致,上面Python参数个数为1,所以这里给的长度为1
//移动机械臂MovJ到这个位姿下去
//给PyList对象的每个元素赋值
PyList_SetItem(PyList, 0, PyFloat_FromDouble(xyz.x()));
PyList_SetItem(PyList, 1, PyFloat_FromDouble(xyz.y()));
PyList_SetItem(PyList, 2, PyFloat_FromDouble(xyz.z()));
PyList_SetItem(PyList, 3, PyFloat_FromDouble(quaternion.w()));
PyList_SetItem(PyList, 4, PyFloat_FromDouble(quaternion.x()));
PyList_SetItem(PyList, 5, PyFloat_FromDouble(quaternion.y()));
PyList_SetItem(PyList, 6, PyFloat_FromDouble(quaternion.z()));
PyTuple_SetItem(ArgList, 0, PyList);//将PyList对象放入PyTuple对象中
PyObject_CallObject(pMovJ,ArgList);
Py_DECREF(PyList);
Py_DECREF(ArgList);
- 需要传入python的参数为整型的
PyObject *pArg = PyTuple_New(1);
PyTuple_SetItem(pArg, 0, Py_BuildValue("i", 1));//0—序号 i表示创建int型变量
PyObject_CallObject(pEnableMotor, pArg);
处理python返回值
- 需要处理从python返回为list到c++的
PyObject * p_pose = PyObject_CallObject(pGetCurrentPose, nullptr);
if(p_pose == nullptr)
{
ROS_ERROR("Error: p_pose == nullptr");
PyErr_Print();
return false;
}
std::vector<double> v_current_pose;
if(p_pose && PyList_Check(p_pose))
{
int i_size = PyList_Size(p_pose);
if(i_size <= 0)
{
ROS_ERROR("获取机械臂当前位姿失败");
return false;
}
for (int i = 0; i < i_size; ++i)
{
PyArg_Parse(PyList_GET_ITEM(p_pose, i), "d", &temp);
v_current_pose.push_back(temp);
}
if(v_current_pose.size() != 7)
{
ROS_ERROR("获取机械臂当前位姿包含变量为:%d",(int)v_current_pose.size() );
return false;
}
}
注:如果python脚本执行出错,会导致PyObject_CallObject返回值为nullptr