在ubuntu中,使用python调用C++代码

博主因工程需要,总结在Ubuntu中用Python调用C++代码的方法。若C++函数无返回值或无需传参,可使用Python自带的ctypes库;若要传递vector类型的值,可使用pybind11库。还介绍了编写CMakeLists.txt文件等相关操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        最近因为工程需要,需要在ubuntu中使用python调用C++代码,我在网上参考了比较多的资料,在此做一个总结。

        如果需要被调用的c++函数中,都没有返回值或者不需要进行传参,则使用ctypes库,这个库比较简单,而且python自带,不需要下载,直接import即可。具体使用方法如下所述。

一、使用cyptes调用C++代码

        1.将c++代码使用extern封装,在这里我自己新建了一个calbypython.cpp文件专门封装c++的接口。此文件的代码如下图所示。

        可以看到,我的每个函数都没有返回值,之所以定义了calibration和registeration两个类,是因为下面的get_measured_pts_python()这些函数用了我类里面的方法,如下图所示。这些函数的定义根据自己的代码来。

        2.编写CMakelists.txt文件,我觉得编写CMakelists.txt文件是一件优雅而又倍让人受折磨的活。之所以要编写这个文件,是为了让你写的c++文件被编译成一个.so文件,以此可以让python去调用,所以需要增加的部分是下面几行。其中add_library则是把我${SOURCE}变量里面的所有c++文件编译成.so后缀的动态链接库,注意:SHARED这个是必写的,而${SOURCE}变量你可以换成你的.cpp文件的路径,例如./src/main.cpp,这个由自己文件构成决定,我则是这么定义${SOURCE}变量的,aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SOURCE),后面的target_include_directories和target_link_libraries则是导入包的头文件和动态链接库文件,没有的可以不写。就比如我需要opencv、pcl和halcon的库,我后面就写了${INC_DIRS}、${PCL_LIBRARIES}、${OpenCV_LIBRARIES}和${LIBS})这几个变量,这些变量是可以换成自己的路径。写完之后编译就可以得到动态链接库了。

如果觉得我的方法过于复杂或者难懂,则可以参考如下链接:

Ubuntu16.04中python调用C++_ubuntu、python调用cpp-CSDN博客

        3.在python中调用刚刚生成的动态链接库。

        这个部分可以直接参考上面给的链接,比较简单。

二、使用pybind11调用c++代码

        先开始我是使用的ctypes,用的还挺好,直到我想将c++中的一个vector类型的值传递给python,才发现ctypes不支持这种类型的传参,经过多方查阅资料,最后选择使用pybind11来进行c++代码调用。

        如和安装库以及整体流程如下链接所示。

pybind11使用记录---ubuntu下使用cmake编译c++工程为python库_pybind11_add_module-CSDN博客

        需要注意的地方:我使用的python是anaconda中的虚拟环境,所以在编写CMakelists.txt文件时,需要指定python的编译器。如下图所示。

      

而我的calbypython.cpp文件也改成了:

        

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、付费专栏及课程。

余额充值