C++如何调用Python自定义模块?

C++如何调用Python自定义模块?


安装Python pybind11模块

pip3 install pybind11 -i https://pypi.tuna.tsinghua.edu.cn/simple

Python基础代码示例

这里使用一位兄弟博客的代码:
https://blog.csdn.net/sunny23666/article/details/109479950

cat >> c_test.py << EOF
class Dog():
    def __init__(self, name, action):
        self.name=name
        self.action=action

    def get_name(self):
        return self._name

    def get_action(self):
        return self.action

    def add(self,i,j):
        print ("Hi")
        return i+j

    def type_test(self,a):
        n=list()
        if a==1:
            n={1, 2, 3}
        else:
            n={5, 5, 5}
        print("type test")
        return n

    def dict_test(self,b):
        d=dict()
        if b==1:
            d={"wo":2, "ni":3}
        else:
            d={"hei" :3, "ha":5}
        return d

    def set_test(self,c):
        e=set()
        if c==1:
            e={1,2,3,3}
        else:
            e={2,3,3,3}
        return e

    def tuple_test(self,d):
        f=tuple()
        if d==1:
            f=(5, 6, 7)
        else:
            f=(7,8,9)
        return f
EOF

C++代码示例

这里使用一位兄弟博客的代码:
https://blog.csdn.net/sunny23666/article/details/109479950

cat >> main.cpp <<
#include <pybind11/embed.h>
#include<iostream>
#include<pybind11/stl.h>
namespace py=pybind11;
int main() {
  py::scoped_interpreter python;
  py::print("hello world");
  //用py::object导入python类模块并进行类的初始化
  py::object Dog=py::module::import("c_test").attr("Dog");
  py::object obj=Dog("miao", "sit");

  // function_test
  py::object add=obj.attr("add");
  py::object result2=add(2,4);
  //注:python返回值到c++中需要类型转换,用cast<数据类型>()来进行转换

  int n=result2.cast<int>();
  std::cout<<n<<std::endl;

  //list_test 集合类型
  py::object type_test=obj.attr("type_test");
  py::object result3=type_test(2);
  py::list v=result3.cast<py::list>();
  std::cout<<v<<std::endl;

  //dict_test 字典类型
  py::object dict_test=obj.attr("dict_test");
  py::object result4=dict_test(1);
  py::dict dd=result4.cast<py::dict>();
  std::cout<<dd<<std::endl;

  //set_ test  列表类型
  py::object set_test=obj.attr("set_test");
  py::object result5=set_test(3);
  py::set ss=result5.cast<py::set>();
  std::cout<<ss<<std::endl;

  //tuple_ test  元组类型测试
  py::object tuple_test=obj.attr("tuple_test");
  py::object result6=tuple_test(1);
  py::tuple tt=result6.cast<py::tuple>();
  std::cout<<tt<<std::endl;
  return 0;
}
EOF

编写cmake配置

##方式一:

cat >>CMakeLists.txt <<EOF
# 建议使用CMake3.12+以支持现代Python查找
cmake_minimum_required(VERSION 3.12) 
project(pf_test)

# 设置 C++11 标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 查找Python解释器和库
# 可以利用cmake内置的自动发现配置,或者像下面方式二手动指定,手动指定需要我们自己找到对应目录
find_package(Python REQUIRED COMPONENTS Interpreter Development)
# 不能使用如下方式,cmake自动发现机制要求安装的pybind11下有配置Config.cmake文件,或者cmake内置有Findxxx.cmake
# find_package(pybind11 REQUIRED /software/py_c_ext/lib/python3.12/site-packages/pybind11/include/)

# 添加可执行文件或库
add_executable(pf_test # 生成执行文件
    main.cpp
)

# 查找 pybind11(确保已安装 pybind11)
# 使用find_package自动查找到的头文件
target_include_directories(pf_test PRIVATE Python)
# 这里需要指定完整路径,不能像上面Python头文件一样自动发现。
target_include_directories(pf_test PRIVATE /software/py_c_ext/lib/python3.12/site-packages/pybind11/include/)

# 链接Python, 不需要链接pybind11,因为我们已经在代码中引入了头文件,Python为pybind11所依赖的
target_link_libraries(pf_test PRIVATE
    Python::Python
)

# 设置输出文件名(可选)
set_target_properties(pf_test PROPERTIES
    PREFIX ""
    SUFFIX ".exe"  # 生成后缀.exe执行文件
)
EOF


##方式二:

cat >>CMakeLists.txt <<EOF
# 建议使用 CMake 3.12+ 以支持现代 Python 查找
cmake_minimum_required(VERSION 3.12)
project(pf_test)

# 设置C++11标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 查找Python 解释器和库
#find_package(Python REQUIRED COMPONENTS Interpreter Development)

# 添加可执行文件或库
add_executable(pf_test # 生成执行文件
    main.cpp
)

# 查找 pybind11(确保已安装 pybind11)
# 头文件路径怎么获取吗?
# python -c "import sysconfig; print(sysconfig.get_path('include'))"
target_include_directories(pf_test PRIVATE /usr/include/python3.12)
# 一般性的pip安装路径,可以通过Python搜索路径查找。
# python3 -c "import sys; print(sys.path)"
target_include_directories(pf_test PRIVATE /software/py_c_ext/lib/python3.12/site-packages/pybind11/include/)

# 链接Python
# Python::Python
# 不用上面find_package的自动发现机制,我们手动指定了路径,这个路径怎么获取吗?
# python3 -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))"
target_link_libraries(pf_test PRIVATE
    /usr/lib/x86_64-linux-gnu/libpython3.12.so
)

# 设置输出文件名(可选)
set_target_properties(pf_test PROPERTIES
    PREFIX ""
    SUFFIX ".exe"  # 生成后缀.exe执行文件
)
EOF

执行

# 将上面三个文件保存后,放在同一个目录下,比如src
mkdir src && cd src
# 创建上面三个文件
...
# 创建构建目录
mkdir build && cd build
# 执行构建
cmake ..
make
# 构建完成后复制执行文件到src目录下,因为py脚本在该目录
cp pf_test.exe ../
# 运行
./pf_test.exe

备注

这里面的关键点在于c++依赖包pybind11中py::module::import方法,导入Python代码,通过pybind11内置的属性或者方法去加载py脚本使用。而我们通过Python调用C++模块则是通过PYBIND11_MODULE(example, m)提供给Python使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值