You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用pybind11在Python中调用C++对象时的类型转换报错问题

解决pybind11嵌入模式下C++自定义对象转Python对象的cast_error问题

最近在做pybind11嵌入Python的项目时,踩了个实实在在的坑:编译全程无报错,一运行就直接崩溃,卡在py::cast(car1)这行,抛出pybind11::cast_error,错误信息是'make_tuple(): unable to convert argument of type 'object' to Python object'。折腾了半天终于搞懂了原因,下面把问题代码、分析和解决方案分享给大家。

问题代码回顾

main.cpp

// Embeding the interpreter into c++ 
#include <pybind11/embed.h>
#include <iostream>
#include <string>
namespace py = pybind11;

class Vehiclee {
public:
int vehicle_id;
std::string vehicle_name;
std::string vehicle_color;
void printname() {
std::cout << "Vehicle id is: " << vehicle_id;
std::cout << "Vehicle name is: " << vehicle_name;
std::cout << "Vehicle color is: " << vehicle_color;
}
};

int main() {
py::scoped_interpreter python;
py::module simpleFuncs = py::module::import("simpleFuncs");

Vehiclee car1;
car1.vehicle_id = 1234;
car1.vehicle_name = "VehicleName";
car1.vehicle_color = "red";

py::object car2 = py::cast(car1); // <-- 崩溃触发点
simpleFuncs.attr("simplePrint")(car2);
return 0;
}

simpleFuncs.py

def simplePrint(argument):
    print(argument)

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(wrapper)
add_subdirectory(pybind11)
add_executable(wrapper main.cpp)
target_link_libraries(wrapper PRIVATE pybind11::embed)

问题根源

说白了就是pybind11根本不知道怎么把你的自定义C++类Vehiclee转换成Python对象。它只自带了基础类型(int、string、STL容器等)的转换规则,对于你自己写的类,必须主动给它一套映射规则——也就是绑定类的属性和方法,告诉它如何处理这个自定义类型。

解决方案:给自定义类添加pybind11绑定

我们需要在C++代码里添加一个嵌入模式专用的模块绑定,用PYBIND11_EMBEDDED_MODULE宏来定义,把Vehiclee类的属性和方法暴露给Python。

修改后的main.cpp

// Embeding the interpreter into c++ 
#include <pybind11/embed.h>
#include <iostream>
#include <string>
namespace py = pybind11;

class Vehiclee {
public:
int vehicle_id;
std::string vehicle_name;
std::string vehicle_color;
void printname() {
std::cout << "Vehicle id is: " << vehicle_id << "\n";
std::cout << "Vehicle name is: " << vehicle_name << "\n";
std::cout << "Vehicle color is: " << vehicle_color << "\n";
}
};

// 关键新增:定义嵌入模式的模块,绑定Vehiclee类
PYBIND11_EMBEDDED_MODULE(cpp_classes, m) {
    m.doc() = "Embedded module exposing C++ classes to Python"; // 模块说明
    py::class_<Vehiclee>(m, "Vehiclee")
        .def_readwrite("vehicle_id", &Vehiclee::vehicle_id)    // 暴露公共属性
        .def_readwrite("vehicle_name", &Vehiclee::vehicle_name)
        .def_readwrite("vehicle_color", &Vehiclee::vehicle_color)
        .def("printname", &Vehiclee::printname);              // 暴露成员方法
}

int main() {
py::scoped_interpreter python;

// 可选:导入我们的C++绑定模块(如果Python代码要直接实例化Vehiclee的话需要)
py::module cpp_classes = py::module::import("cpp_classes");

py::module simpleFuncs = py::module::import("simpleFuncs");

Vehiclee car1;
car1.vehicle_id = 1234;
car1.vehicle_name = "VehicleName";
car1.vehicle_color = "red";

// 现在可以直接传递C++对象,pybind11自动处理转换,不需要手动cast
simpleFuncs.attr("simplePrint")(car1);

// 手动转成py::object也完全没问题了
py::object car2 = py::cast(car1);
simpleFuncs.attr("simplePrint")(car2);

return 0;
}

升级simpleFuncs.py(测试属性访问)

既然绑定了属性,我们可以在Python里直接访问C++对象的成员:

def simplePrint(argument):
    print("Received C++ object:", argument)
    # 直接访问C++对象的属性
    print("Vehicle ID:", argument.vehicle_id)
    print("Vehicle Name:", argument.vehicle_name)
    print("Vehicle Color:", argument.vehicle_color)
    # 调用C++对象的成员方法
    argument.printname()

编译运行

还是用原来的步骤:

git clone https://github.com/pybind/pybind11
cmake .
make
./wrapper

现在运行就不会崩溃了,还能看到Python打印出C对象的属性,以及C方法执行的输出。

总结

不管是pybind11的扩展模式(写Python模块)还是嵌入模式(C调用Python),**自定义C类必须先通过py::class_绑定,pybind11才能处理它和Python对象之间的转换**。没有绑定的自定义类型,pybind11根本不知道怎么序列化/反序列化,自然会抛出转换错误。

内容的提问来源于stack exchange,提问作者Blind0ne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:04:28