Nanobind传递Python类型至C++函数并实现类型转换及日期转换
实现Python类型驱动的Parameter类(Nanobind)
核心类型转换逻辑
构造函数接收Python类型对象后,基于该类型对输入值做对应转换:
- 用
nb::handle包装Python类型对象并存储为类成员 - 转换时先判断输入值类型,再匹配目标类型执行转换逻辑
- 针对datetime这类特殊类型,单独处理字符串转对象的逻辑
日期字符串转datetime实现
借助Python标准库datetime的strptime方法完成转换,通过Nanobind调用Python API:
- 提前导入Python的
datetime.datetime类和strptime方法 - 对输入的日期字符串调用
strptime,指定格式为%Y-%m-%d - 捕获转换失败的异常,抛出明确的错误信息
完整实现代码
#include <nanobind/nanobind.h> #include <nanobind/stl/string.h> #include <nanobind/exception.h> #include <string> namespace nb = nanobind; class Parameter { private: nb::handle m_target_type; // 预加载Python datetime相关对象,避免重复查找 static nb::handle s_datetime_cls; static nb::handle s_strptime_func; public: // 构造函数:传入目标Python类型 Parameter(nb::handle target_type) : m_target_type(target_type) { // 仅首次初始化datetime静态成员 if (!s_datetime_cls.is_valid()) { nb::module_ dt_module = nb::module_::import("datetime"); s_datetime_cls = dt_module.attr("datetime"); s_strptime_func = s_datetime_cls.attr("strptime"); } } // 转换方法:输入原始值(来自JSON dict的PyObject),返回转换后的值 nb::object convert(nb::handle value) const { // 处理datetime类型的字符串转换 if (m_target_type.is(s_datetime_cls) && nb::isinstance<nb::str>(value)) { std::string date_str = nb::cast<std::string>(value); try { return s_strptime_func(date_str, "%Y-%m-%d"); } catch (const nb::python_error&) { nb::raise_value_error("invalid date format, expected YYYY-MM-DD"); } } // 常规类型转换:直接调用Python类型构造函数 try { return m_target_type(value); } catch (const nb::python_error&) { nb::raise_type_error("cannot convert value to target type"); } } }; // 初始化静态成员 nb::handle Parameter::s_datetime_cls; nb::handle Parameter::s_strptime_func; NB_MODULE(parameter_module, m) { nb::class_<Parameter>(m, "Parameter") .def(nb::init<nb::handle>(), "Construct a Parameter with target Python type") .def("convert", &Parameter::convert, "Convert input value to target type"); }
代码优化与问题修正
- 引用计数管理:用
nb::handle替代原始PyObject*管理Python对象,Nanobind自动处理引用计数,避免内存泄漏 - 异常处理:添加类型转换和日期解析的异常捕获,抛出符合Python习惯的
ValueError/TypeError - 性能优化:将datetime相关对象设为静态成员,避免每次转换重复导入模块
- 类型校验:可在构造函数中添加目标类型合法性检查,避免传入不可调用的无效类型
内容的提问来源于stack exchange,提问作者Arkhangel
相关产品推荐
相关产品推荐

