前言:
因为最近c++下的工程需要在python下调用,所以需要把c++编译成可供python调用的库,记录一下具体做法:
编译c++有多种方法,因为我的是cmake构建的工程,所以直接在cmake的基础上编译成python库(c++中用了第三方库opencv和boost)
下载编译pybind11
下载pybind11:git clone https://github.com/pybind/pybind11.git
安装pytest: pip install pytest
编译:
操作C++代码
我的做法是将编译好的pybind11文件夹拷贝到了c++工程目录下(这样是方便在编译c++的时候能找到pybind11,当然你也可以通过其他方式,只要能找到pybind11就行)
(我只封装了所需要的函数接口)
将你需要的函数接口定义在一个.cpp文件中,比如说,我在pcc.cpp文件中定义了两个函数(该包含的.h文件就正常包含):
int pcc_encoder() 和 int pcc_decoder()
然后在此文件中加入如下代码:
其中比较重要的是这两句:
m.def("pcc_encoder", &pcc_encoder, "Encoder the pointcloud data");
m.def("pcc_decoder", &pcc_decoder, "Decoder the pointcloud data");
这两句代码表明了可供python调用的函数接口,没有在此操作的函数python是找不到的
修改CMakeLists.txt
(只需改动几处即可,第三方库的include和链接基本和c++编译一样)
可以看到只需要修改原本文件的几个地方就可以:
set(LIBRARY_OUTPUT_PATH ../)
这个的意思是设置生成的python库的位置
add_subdirectory(pybind11)
这个是用来增加pybind11的目录,因为之前我把pybind11放在了c++的工程目录下,所以可以直接顺利找到
pybind11_add_module(Pypcc ${PROJECT_SOURCE_DIR}/src/pcc.cpp ${dso_SOURCE_FILES})
这个的意思对应于编译c++的add_executable命令,就是说把哪些文件编译成python库,Pypcc是取的库的名字
target_link_libraries(Pypcc PRIVATE
${Boost_LIBRARIES}
${OpenCV_LIBS}
)
这里是链接第三方库,注意要加上PRIVATE
然后按照一般的c++编译步骤就可以了(进入到新建的build文件夹,执行cmake .. 再执行make),编译完成之后我们可以看到在指定目录下生成.so文件
编写python调用文件
这里说明一下:因为我的.so文件放在了和.py文件同一目录下,所以可以直接导入
遇到的问题:
- 因为我的.so文件是在python3.6的环境下编译的,所以python2.7环境下导入报出没有这个模块的错误,
原因到底是编译c++环境的原因,还是一开始编译pybind11默认的python环境的原因?后续可以验证一下
这个问题已经解决了:
在编译自己的c++项目的时候,一般来说需要在build中先cmake ..生成makefile文件,如果在这里我们不指定python版本的时候,就会寻找到默认的python版本,比如在我的环境下执行cnake ..,有如下信息输出:
说明此时的python版本是3.6 ,而如果我们想利用pyhton2.7(其他版本也一样,前提是系统里安装了相应的python版本或者虚拟环境),那么在cmake ..的时候就要指定python为2.7版本:在python2.7安装的位置找到库文件/头文件/可执行文件
这时候给出的cmake信息为:
-
-- Found PythonInterp: /usr/bin/python2.7 (found version "2.7.17")
-
-- Found PythonLibs: /usr/lib/x86_64-linux-gnu/libpython2.7.so
然后执行make命令,就会生成可供python2.7导入调用的库
- 因为我需要传二维数组给这个参数,考虑到python和c++之间用纯c语言“沟通”可能会好一点,所以打算以这样的方式传参:
float points[][4]
int nums
但是在编译的时候报出错误:
cannot convert ‘pybind11::detail::type_caster<float, void>::cast_op_type<float (*&&)[4]> {aka float*}’ to ‘float (*)[4]’ in argument passing
看到有人说pybind11不支持这种指针类型???这里还没弄清楚
后面我的解决方法是使用STL vector进行传参的,c++中的STL与python是有类型对应的:
前提是要在之前的.cpp文件中包含一个头文件
#include <pybind11/stl.h>
- 在c++中,一般在.h中声明一个函数的时候,可以赋给参数默认值,这样在调用的时候如果默认值的参数没有传进来,那么函数就是用其默认值,但是如果某个函数作为python接口供python调用,即使在c++中声明了默认值,python调用的时候也要将全部参数传参,否则会出现参数不匹配的错误
与opencv通信
最近遇到的问题是希望使用Python cv2读取图片,然后将其传入到c++中处理,这实际上涉及到opencv读取图像在Python和C++中的转换问题.
在C++中读取的图片类型是cv::Mat, 这是opencv中定义的类型,使用起来很方便,在Python中读取的图片类型是numpy.ndarray
类,也就是第三方库numpy的类型, 因此需要定义函数对其进行转换,这里引用了https://blog.csdn.net/non_hercules/article/details/105095153/ 的工作:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2015-08-25 linux fork函数与vfork函数
2015-08-25 简单字符设备驱动程序
2015-08-25 fork与vfork的区别
2015-08-25 进程创建函数fork()、vfork() ,以及excel()函数
2014-08-25 error while loading shared libraries: xxx.so.x"错误的原因和解决办法