如何用Swig实现Python datetime对象到C++ DateTime的无缝传递?
实现思路:Python datetime 转 C++ DateTime 结构体的 SWIG Typemap
核心逻辑
要让Python的datetime.datetime对象无缝传入C++函数,需编写SWIG输入typemap,完成两个关键转换:
- 从Python datetime对象计算出纪元以来的纳秒数(
uint64_t类型) - 将该数值填充到C++的
DateTime结构体中
具体实现步骤
1. 编写SWIG Typemap代码
在你的SWIG接口文件(.i)中添加以下typemap:
%typemap(in) DateTime { // 校验输入是否为Python datetime对象 if (!PyDateTime_Check($input)) { PyErr_SetString(PyExc_TypeError, "Expected a datetime.datetime object"); return NULL; } // 提取datetime的年、月、日等字段 PyDateTime_DateTime* dt = (PyDateTime_DateTime*)$input; int year = PyDateTime_GET_YEAR(dt); int month = PyDateTime_GET_MONTH(dt); int day = PyDateTime_GET_DAY(dt); int hour = PyDateTime_GET_HOUR(dt); int minute = PyDateTime_GET_MINUTE(dt); int second = PyDateTime_GET_SECOND(dt); int microsecond = PyDateTime_GET_MICROSECOND(dt); // 构造tm结构体(注意tm_year从1900开始计数,tm_mon从0开始) struct tm tm_time = {0}; tm_time.tm_year = year - 1900; tm_time.tm_mon = month - 1; tm_time.tm_mday = day; tm_time.tm_hour = hour; tm_time.tm_min = minute; tm_time.tm_sec = second; // 转换为epoch秒数 time_t epoch_sec = mktime(&tm_time); if (epoch_sec == -1) { PyErr_SetString(PyExc_ValueError, "Invalid datetime value"); return NULL; } // 计算总纳秒数:秒数*1e9 + 微秒数*1e3 uint64_t epoch_ns = (uint64_t)epoch_sec * 1000000000ULL + (uint64_t)microsecond * 1000ULL; // 填充到C++ DateTime结构体 $1.epochns = epoch_ns; } // 可选:添加类型检查typemap,让SWIG优先识别datetime对象 %typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) DateTime { $1 = PyDateTime_Check($input) ? 1 : 0; }
2. 接口文件引入Python datetime依赖
在SWIG接口文件开头添加必要的头文件和声明,确保能调用Python datetime API:
%module your_module_name // 引入Python datetime支持 %include <pyhead.swg> %{ #include <Python.h> #include <datetime.h> #include <time.h> #include <stdint.h> // 你的C++结构体与函数声明 struct DateTime { uint64_t epochns; }; void print(DateTime ts); %} // 导出结构体和函数到Python struct DateTime { uint64_t epochns; }; void print(DateTime ts);
3. 关键注意事项
- 时区处理:上述代码默认使用本地时区转换,若需处理UTC时间,可将
mktime替换为timegm(部分平台需定义_BSD_SOURCE或自行实现UTC转epoch逻辑)。 - 范围校验:
uint64_t能覆盖的时间范围是1970年至约5849年,超出该范围的datetime会导致溢出,需根据业务需求添加额外校验。 - 编译依赖:编译时需确保编译器能找到Python的头文件与库,链接datetime模块。
4. Python端使用示例
编译生成Python扩展后,即可直接传入datetime对象:
from datetime import datetime import your_module_name // 直接调用C++函数,传入datetime对象 your_module_name.print(datetime(1985,7,1))
内容的提问来源于stack exchange,提问作者Henrique Bucher
相关产品推荐
相关产品推荐

