ubuntu下C++调用python3.5的类

一、示例代码

python示例如下:

# my_test.py

class Person:
    def __init__(self):
        self.name = 'wdx'
        self.age = 23

    def set_msg(self, name, age):
        self.name = name
        self.age = age

    def get_msg(self):
        print('python: name={}, age={}'.format(self.name, self.age))
        return self.name, self.age

C++如下:

#include 
...

int main(int a, char** b)
{
    PyObject *pModule, *pDict, *pFRCNN, *pFrcnn;
    PyObject *result, *result1;
    
    //初始化python
    Py_Initialize();
    if (!Py_IsInitialized())
    {
        printf("python初始化失败!");
        return 0;
    }
    //引入当前路径,否则下面模块不能正常导入
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('../tf-faster-rcnn/tools')");
    //引入py文件
    pModule = PyImport_ImportModule("my_test");
    // pModule = PyImport_ImportModule("demo");
    assert(pModule != NULL);
    //获取模块字典,即整个py文件的对象
    pDict = PyModule_GetDict(pModule);
    assert(pDict != NULL);
    //通过字典属性获取模块中的类
    pFRCNN = PyDict_GetItemString(pDict, "Person");
    // pFRCNN = PyDict_GetItemString(pDict, "Faster_RCNN");
    assert(pFRCNN != NULL);
    // 实例化faster-rcnn检测器
    pFrcnn = PyObject_CallObject(pFRCNN, nullptr);
    assert(pFrcnn != NULL);

    PyRun_SimpleString("print('-'*10, 'Python start', '-'*10)");
    // 调用类的方法
    result = PyObject_CallMethod(pFrcnn, "get_msg", "");
    PyObject_CallMethod(pFrcnn, "set_msg", "si", "tyl", 24);
    result1 = PyObject_CallMethod(pFrcnn, "get_msg", "");
    // 创建参数
    // PyObject *pArgs = PyTuple_New(2); //函数调用的参数传递均是以元组的形式打包的,2表示参数个数

    //输出返回值
    char* name;
    int age;
    PyArg_ParseTuple(result, "si", &name, &age);
    printf("%s-%d\n", name, age);
    PyArg_ParseTuple(result1, "si", &name, &age);
    printf("%s-%d\n", name, age);

    PyRun_SimpleString("print('-'*10, 'Python end', '-'*10)");

    //释放python
    Py_DECREF(pFrcnn);
    Py_Finalize();
}

2、注意点

1、python脚本里的路径都不要写相对路径!

     如:cv2.imread('../data/demo/111.jpg')  错!!

     要写绝对路径:cv2.imread('/home/.../data/demo/111.jpg') 

2、

PyTuple_New创建的参数不可以重复赋值,否则最后的数据都是最后赋的值。

正确的示例:

// mat图像转PyObject格式
PyObject *Func::mat_to_pyobj(Mat &im) {
    PyObject *pIm = PyTuple_New(int(im.rows));    // 图像数据
    for (int row = 0; row < im.rows; row++) {   // 行
        PyObject *pRow = PyTuple_New(int(im.cols));    // 新建每一行
        for (int col = 0; col < im.cols; col++) {   // 列
            PyObject *pPt = PyTuple_New(3);    // 像素点   BGR
            PyTuple_SetItem(pPt, 0, Py_BuildValue("i", static_cast(im.at(row, col)[0])));
            PyTuple_SetItem(pPt, 1, Py_BuildValue("i", static_cast(im.at(row, col)[1])));
            PyTuple_SetItem(pPt, 2, Py_BuildValue("i", static_cast(im.at(row, col)[2])));

            PyTuple_SetItem(pRow, col, pPt);    // 添加行像素

        }
        PyTuple_SetItem(pIm, row, pRow);
    }

    return pIm;
}

3、调用的python函数如果有返回值,不要只返回一个,至少返回两个

return result, 1

4、在ros中使用c++调用python时,要在cmakelists中包含以下部分

set(CMAKE_CXX_STANDARD 14)
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
)

catkin_python_setup()

catkin_package(
  CATKIN_DEPENDS
  roscpp
  rospy
)

target_link_libraries(mir100_jaco7_voice_record_node    # 节点名
  python3.5m
  ${catkin_LIBRARIES}
)

target_link_libraries(mir100_jaco7_voice_command_node    # 节点名
  python3.5m
  ${catkin_LIBRARIES}
)

 

你可能感兴趣的:(语言混编,C++,python35)