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 <python3.5/Python.h>
...

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<int>(im.at<Vec3b>(row, col)[0])));
            PyTuple_SetItem(pPt, 1, Py_BuildValue("i", static_cast<int>(im.at<Vec3b>(row, col)[1])));
            PyTuple_SetItem(pPt, 2, Py_BuildValue("i", static_cast<int>(im.at<Vec3b>(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}
)

 

Ubuntu系统中,如果你想用Python调用C++编写的函数,你需要创建一个C++的共享库(动态链接库),然后通过Python的`ctypes`库或者`cffi`库来调用这个库中的函数。下面是一个简单的示例来说明这个过程: **步骤 1: 编写C++函数** 首先,你需要有一个C++源文件,比如`add.cpp`,它包含你想要在Python调用的函数: ```cpp // add.cpp extern "C" { #include <Python.h> } extern "C" { PyObject* add(PyObject* /*self*/, PyObject* args) { int a, b, result; if (!PyArg_ParseTuple(args, "ii", &a, &b)) return NULL; result = a + b; return PyLong_FromLong(result); } static PyMethodDef AddMethods[] = { {"add", add, METH_VARARGS, "Add two integers"}, {NULL, NULL, 0, NULL} // Sentinel }; static struct PyModuleDef addmodule = { PyModuleDef_HEAD_INIT, "addmodule", NULL, -1, AddMethods }; PyMODINIT_FUNC PyInit_addmodule() { return PyModule_Create(&addmodule); } } ``` **步骤 2: 编译C++代码为共享库** 接下来,使用g++编译器编译这个C++文件为共享库: ```sh g++ -shared -fPIC -o libadd.so -I/usr/include/python3.x add.cpp ``` 这里的`-I/usr/include/python3.x`是指定Python头文件的路径,`x`是你当前Python版本的主版本号(例如,对于Python 3.8,使用`3.8`)。 **步骤 3: 在Python中使用ctypes调用C++函数** 现在,你可以在Python脚本中导入并使用这个共享库了: ```python import ctypes # 加载共享库 lib = ctypes.CDLL('./libadd.so') # 调用函数 result = lib.add(4, 5) print(result) # 输出: 9 ``` 确保将`./libadd.so`替换为你的共享库文件的正确路径。 **步骤 4: 清理工作** 在每次修改C++代码并重新编译后,需要重启Python进程,或者在Python中使用`ctypes.cdll.Reload`来重新加载共享库,以便使用新的修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值