[工程编写]cmakelist多版本python环境编写

问题:最近在写一个工程的时候需要用到python3,但是由于引入了ROS相关的环境,导致希望使用python3的那部分代码一直默认使用ROS中的python2,这样环境就不对了。
解决的方法:很顺理成章的想法是为需要python3的那部分代码专门指定一个python3的环境,这需要在cmakelist中单独指出

方法

多目录CmakeLists.txt

大伙可能经常见到一些开源的工程中存在多个CmakeLists.txt,这么做的目的本质上是将代码分成好多块,每一块有一个单独CmakeLists.txt管理,最后只需一个总的CmakeLists.txt进行汇总即可。注意:此处掌管一块代码的CmakeLists.txt即可完成我们希望的功能。最简单的例子如下,我们有一个hello库+一个world库,他们俩又汇总成一个最终代码库,就有如下的工程目录结构:
在这里插入图片描述

而我们希望控制其中一个代码块的python版本并在主文件中调用这部分代码,我建议的代码格式为:
project_name/
——cmake
   ——sub_project_name.cmake
—— include
——src
——CmakeLists.txt(主)
——third_party
   ——sub_project_name
      ——include
      ——src
      ——CmakeLists.txt(子)
以上结构中,project_name为主文件夹,sub_project_name为我们希望控制python版本代码的代码块所在的子文件夹中,我们将他放在third_party中方便管理。接下来就要编写CmakeLists.txt了,关于其如何编写可以看看我之前的文章

指定子库CmakeLists.txt中python版本

子库中的CmakeList.txt写法和正常情况基本相同,只不过将add_executable替换为了add_library,我们要在其中准确地指定python版本

cmake_minimum_required(VERSION 3.12.0)
project(CallAPI)

set( CMAKE_CXX_FLAGS "-std=c++14 -O3" )

SET(Python3_INCLUDE_DIRS "/usr/include/python3.6m")
SET(Python3_LIBRARIES "/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu/libpython3.6.so")
SET( PYTHON_EXECUTABLE /usr/bin/python3.6)
# find_package(Python3 COMPONENTS Interpreter Development REQUIRED)
message("Python3: " ${Python3_INCLUDE_DIRS})
message("Python3: " ${Python3_LIBRARIES})


include_directories(./include/ ${Python3_INCLUDE_DIRS})

add_library(libCallAPI src/call_api.cpp)

target_link_libraries(libCallAPI ${Python3_LIBRARIES})

主CmakeLists.txt中连接子库

如我在之前的文章所讲,这边建议写一个sub_project_name.cmake文件来连接库,以我写的CallAPI库为例,.cmake内容如下

add_subdirectory(${PROJECT_SOURCE_DIR}/thirdparty/CallAPI)
include_directories(${PROJECT_SOURCE_DIR}/thirdparty/CallAPI/include/)
list(APPEND ALL_TARGET_LIBRARIES libCallAPI)

有了.cmake文件,在主CmakeLists.txt中只需要应用一下这个文件即可

...其他内容...
include(cmake/callapi.cmake)
...其他内容...

总结

如上,sub_project_name库的python版本就是你特定的那个版本,不会收到主或者其他CmakeLists.txt的影响啦。举一反三,当需要其他依赖的多版本环境时同样可以使用以上方法。

首先,需要确保QT cplusplus程序和pyQT程序都已经正确编译并且可以正常运行。 对于信号和槽的绑定,在QT中,可以使用QObject::connect()函数来实现。在CMakeLists文件中,你需要添加以下内容: 1. 安装python库和pyQT库:在CMakeLists中添加以下命令: ``` find_package(PythonLibs REQUIRED) find_package(Qt5 COMPONENTS Widgets REQUIRED) include_directories(${PYTHON_INCLUDE_DIRS}) ``` 2. 添加pyQT代码文件:在CMakeLists中添加需要使用的pyQT代码文件。例如,如果你想使用hello.py中的功能: ``` set(PYTHON_FILES hello.py ) ``` 3. 添加C++代码文件:在CMakeLists中添加需要使用的C++代码文件和头文件。 ``` add_executable(main main.cpp widget.cpp widget.h ) ``` 4. 链接QT库和python库:在CMakeLists中添加以下命令: ``` target_link_libraries(main Qt5::Widgets ${PYTHON_LIBRARIES} ) ``` 5. 建立链接:在widget.cpp中添加以下代码来建立C++和python之间的链接: ``` #include <QMetaObject> #include <QMetaMethod> #include <QMetaClassInfo> #include <Python.h> // 获取pyqt模块 PyObject* module = PyImport_ImportModule("hello"); if (!module) { qDebug()<<"failed to import module"; } // 获取pyqt类 PyObject* classObj = PyObject_GetAttrString(module, "Hello"); if (!classObj) { qDebug()<<"failed to find class"; } // 利用pyqt类创建实例 PyObject* instance = PyObject_CallObject(classObj, nullptr); if (!instance) { qDebug()<<"failed to create instance"; } // 获取信号和槽列表 const QMetaObject* metaObject = instance->metaObject(); int methodCount = metaObject->methodCount(); for (int i = 0; i < methodCount; ++i) { const QMetaMethod method = metaObject->method(i); if (method.methodType() != QMetaMethod::Signal) { continue; } const QByteArray signalName = method.signature(); QMetaClassInfo pySlot = metaObject->classInfo(i + metaObject->methodCount()); const QByteArray slotName = pySlot.value(); PyObject* methodObj = PyObject_GetAttrString(instance, slotName.constData()); if (!methodObj) { qDebug()<<"failed to find method "<<slotName; } Py_XINCREF(methodObj); const char* signal = signalName.constData(); const char* slot = slotName.constData(); qDebug() << "BINDING SIGNAL AND SLOT:" << signal << slot; bool success = QObject::connect( this, signal, methodObj, PyString_AsString(PyObject_Repr(methodObj))); if (!success) { qDebug()<<"failed to connect signal "<<signal; } } ``` 这个函数的目的是获取pyQT类的实例并在C++和python之间建立信号和槽的连接。 注意:以上代码仅仅是为了验证是否成功连接信号和槽,并不是最佳实践。最好的方法是将业务代码分成两层,分别是C++和python代码,让它们彼此独立工作,通过接口进行交互。 希望以上内容可以帮助到你。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值