ROS工程中C++调用python函数

版权声明: https://blog.csdn.net/u014610460/article/details/80635701

在ROS api程序中,大部分函数的实现是用的python,python语言简单易学,特别做一些测试和调试非常简单。

因此,在C++中调用python函数会极大地减少工作量。


在C++中调用python函数


C++调用python函数,python中用有Python.h头文件起到了很大作用。相关的函数介绍可在 Extending Python with C or C++ 中找到。(这个是针对python2.7的说明)。

在ros工程中,需在CMakeLists.txt中添加相关依赖项即可,关键代码如下:

link_directories(/usr/lib/python2.7/config-i386-linux-gnu)

include_directories(${catkin_INCLUDE_DIRS} /usr/include)

add_executable(test src/test.cpp)
target_link_libraries(test ${catkin_LIBRARIES} python2.7)   //用于找到libpython2.7.so库

关于C++部分代码如下:

#include <ros/ros.h>
#include <iostream>
#include <python2.7/Python.h>

int main()
{
    Py_Initialize();

    PyRun_SimpleString("print 'test simple demo'");
	//load python functions 
    PyRun_SimpleString("import sys");
    std::string dirs = std::string("sys.path.append('/home/user/test/')");
    PyRun_SimpleString(dirs.c_str());
    //load module
    PyObject *module = PyString_FromString("for_test");
    PyObject *pyModule = PyImport_Import(module);
    if(!pyModule) //failed
    {
        std::cout << "Get python module failed." << std::endl;
        return 0;
    }
    //load function
    PyObject *pyfun = PyObject_GetAttrString(pyModule, "main");
    if(!pyfun || !PyCallable_Check(pyfun))
    {
        std::cout << "Cannot find python function" << std::endl;
        return 0;
    }else{
        std::cout << "load python funtion ok" << "\n";
    }
    //callback funtion
    PyObject *argss = PyTuple_New(1);
    PyObject *arg = PyString_FromString("127.0.0.1");
    PyTuple_SetItem(argss, 0, arg);
    PyObject *pyRes = PyObject_CallObject(pyfun, argss);
    //get result
    if(pyRes)
    {
        std::string ret = PyString_AsString(pyRes);
        std::cout << "result: " << ret << "\n";
    }

    Py_Finalize();
    return 0;
}

其for_test.py的python代码如下:

import logging
import socket
import time

def main(ip):
    proctime = time.strftime("%y%m%d_%H%M%S")
    logging.basicConfig(level=logging.INFO, filename=proctime+'.log')
    logging.info("Start program")
    port = 8080
    clientsocket_ = socket.create_connection((ip, port))
    clientsocket_.send("for test")
    logging.info("write file success")
    logging.info("Ending program")
    return "Test OK"

if __name__ == "__main__":
    main("127.0.0.1")         ## 运行前提为开启了服务器端

上面例子是传入一个参数并得到返回值的python函数调用,更多的调用方式可在网上找到大量相关资料。注意将for_test.py文件放到/home/user/test/下,否则会找不到相应python模块。

通过上述例子,便可以很方便地实现python调用。

不过,发现调用ros自身提供的python函数,比如rostopic中的get_topic_type("/rosout")函数,rosservice中的get_service_list()函数,这些函数都非常好用非常方便。只是通过上述方法总是调用不成功,会出现以下提示:


说“'module' object has no attribute 'argv'" in <module 'threading' from '/usr/lib/python2.7/threading.pyc'> ignored”。但即使删除了threading.pyc也还是不行,原因暂时不明,不知道是否有人已经解决。


猜你喜欢

转载自blog.csdn.net/u014610460/article/details/80635701