Boost.Python 是一个用于实现 C++ 和 Python 之间互操作性的库,它的主要功能包括:
- 转换接口:允许开发者将 C++ 函数和类转换为 Python 可调用的形式,这样在 Python 中就可以直接使用这些 C++ 代码。
- 简化过程:在很多情况下,开发者不需要对原始的 C++ 代码进行任何修改。Boost.Python 会对 C++ 类进行封装,使其编译后符合 Python 的语言规范,从而简化了集成过程。
- 导出对象和方法:可以将 C++ 的函数和对象导出,使得 Python 能够方便地调用这些对象和方法,这是实现 C++ 和 Python 混合编程的关键功能。
- 基本类型导出:提供了一系列的格式和关键字来导出基本类型,例如使用
boost::python::def()
来定义一个可以被 Python 调用的 C++ 函数。 - 模块定义:通过
BOOST_PYTHON_MODULE
宏,可以定义一个可以被 Python 导入的模块,这样可以组织和管理 C++ 提供的接口。
C++编写Python扩展模块:
可以向python暴露C++类中的成员函数和成员数据,直接供python使用
#include <boost/python.hpp>
using namespace boost::python;
#include <iostream>
using namespace std;
struct World
{
World(){
cout << "World()" << endl;
}
World(const string& str){
msg = str;
cout << "World(const string& str)" << endl;
}
World(double,double){
cout << "World(double,double)" << endl;
}
void set(std::string msg) { this->msg = msg; }
double getMyData(){return data2;}
void setMyData(double d){data2 = d;}
std::string greet() { return msg; }
std::string msg;
string name="World AAAAA";
double data;
double data2;
};
BOOST_PYTHON_MODULE(hello)
{
class_<World>("World", init<string>()) //定义python类的构造函数
.def(init<double,double>()) //另一个构造函数
.def("greet", &World::greet) //暴露普通函数
.def("set", &World::set)
.def_readonly("myName", &World::name) //暴露成员数据(只读)
.def_readwrite("myData", &World::data) //暴露成员数据 (读写)
.add_property("myData2", &World::getMyData, &World::setMyData) //暴露属性(属性名和C++成员名可以不同)
;
}
vcpkg+cmake编译代码,生成动态库(linux环境):
project(hello)
add_library(${PROJECT_NAME} SHARED 2.cc)
#不要动态库前缀,生成的动态库名为:hello.so
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
find_package(Boost REQUIRED python311)
find_package(Python3 COMPONENTS Development REQUIRED)
#正常来说应该是Boost::python,但是我的电脑上必须是Boost::python311, 可能是vcpkg的boost上的bug
target_link_libraries(${PROJECT_NAME} PRIVATE Boost::python311 Python3::Python)
python代码中使用生成的动态库:
Boost::Python 不仅能够将 C++ 代码暴露给 Python,还支持在 C++ 中直接调用 Python 脚本。以下是一些关于如何在 C++ 中使用 Boost::Python 来调用 Python 脚本的功能介绍:
- 调用Python函数:可以在C++中直接调用Python脚本中定义的函数。这通常涉及到使用
boost::python::import()
来导入Python模块,然后通过boost::python::object
来调用模块中的函数。 - 执行Python脚本:可以执行Python脚本文件中的代码。这通常需要确保Python脚本文件位于程序的工作目录下,然后在C++代码中指定要执行的Python脚本路径。
- 数据交互:在C++和Python之间传递数据,例如,可以从C++传递参数给Python函数,或者从Python函数返回值给C++程序。
- 类型转换:自动处理C++和Python之间的数据类型转换,使得两种语言间的数据可以安全、正确地传递。
需要注意的是,尽管 Boost::Python 提供了许多便利的功能,但它的实现依赖于 Python/C API,因此在使用时要结合 Python/C API 的相关知识。此外,Boost::Python 的某些功能可能还不完善,需要开发者对 Python/C API 有一定的了解,以便在遇到问题时能够进行调试和解决。
C++中调用Python脚本:
#include <boost/python.hpp> // Boost.Python
#include <iostream>
#include <string>
using namespace std;
using namespace boost::python;
int main(int argc, char* argv[])
{
Py_Initialize(); // 初始化 Python 解释器
try
{
object main_module = import("__main__");
object main_namespace = main_module.attr("__dict__");
exec("import sys", main_namespace);
exec("sys.path.append('')", main_namespace); // 将当前目录添加到Python模块搜索路径
object m = import("MyTest");
object getPidName = m.attr("GetPidName");
object getPids = m.attr("GetPidList");
list lstPid = extract<list>(getPids());
for(int i = 0; i < len(lstPid); i++){
int id = extract<int>(lstPid[i]);
object name = getPidName(id);
str sName = extract<str>(name);
string strName = extract<string>(name);
cout << strName << endl;
}
}
catch (const error_already_set&)
{
PyErr_Print();
return -1;
}
Py_Finalize(); // 终止 Python 解释器
return 0;
}
MyTest.py
#!/usr/bin/python3.11
#encoding=utf-8
import psutil
def GetPidName(pid):
return psutil.Process(pid).name()
def GetPidList():
return psutil.pids()