hikyuu2/hikyuu_pywrap/pybind_utils.h

104 lines
3.1 KiB
C++
Raw Normal View History

2020-06-25 15:59:37 +08:00
/*
2023-12-26 18:25:50 +08:00
* Copyright (c) 2019 hikyuu.org
2020-06-25 15:59:37 +08:00
*
2023-12-26 18:25:50 +08:00
* Created on: 2020-5-25
2020-06-25 15:59:37 +08:00
* Author: fasiondog
*/
#pragma once
2023-12-26 18:25:50 +08:00
#ifndef HIKYUU_PYTHON_BIND_UTILS_H
#define HIKYUU_PYTHON_BIND_UTILS_H
2020-06-25 15:59:37 +08:00
2023-12-26 18:25:50 +08:00
#include <pybind11/pybind11.h>
2023-12-27 02:16:10 +08:00
#include <pybind11/operators.h>
#include <pybind11/stl.h>
2023-12-30 15:34:28 +08:00
#include <pybind11/numpy.h>
2020-06-26 21:39:53 +08:00
#include <vector>
2023-12-26 18:25:50 +08:00
#include <string>
2023-12-27 02:16:10 +08:00
#include "convert_any.h"
#include "pickle_support.h"
#include "ioredirect.h"
2020-06-25 15:59:37 +08:00
2023-12-26 18:25:50 +08:00
namespace py = pybind11;
2020-06-26 21:39:53 +08:00
2023-12-26 18:25:50 +08:00
namespace hku {
2023-12-30 15:34:28 +08:00
template <typename T>
py::bytes vector_to_python_bytes(const std::vector<T>& vect) {
return py::bytes((char*)vect.data(), vect.size() * sizeof(T));
}
template <typename T>
std::vector<T> python_bytes_to_vector(const py::bytes& obj) {
auto bytes_len = len(obj);
if (bytes_len % sizeof(T) != 0) {
throw std::runtime_error("The length bytes not match!");
}
auto vect_len = bytes_len / sizeof(T);
std::vector<T> result(vect_len);
char* buffer = nullptr;
2024-04-14 03:39:45 +08:00
Py_ssize_t length = 0;
2023-12-30 15:34:28 +08:00
if (PyBytes_AsStringAndSize(obj.ptr(), &buffer, &length) != 0) {
throw std::runtime_error("trans bytes to vector failed!");
}
2024-04-14 03:39:45 +08:00
if (length != static_cast<Py_ssize_t>(vect_len * sizeof(T))) {
2023-12-30 15:34:28 +08:00
throw std::runtime_error("The length bytes not match!");
}
memcpy(result.data(), buffer, length);
return result;
}
2023-12-26 18:25:50 +08:00
template <typename T>
2023-12-30 14:25:48 +08:00
std::vector<T> python_list_to_vector(const py::sequence& obj) {
2023-12-26 18:25:50 +08:00
auto total = len(obj);
std::vector<T> vect(total);
for (auto i = 0; i < total; ++i) {
vect[i] = obj[i].cast<T>();
2023-09-24 02:46:04 +08:00
}
2023-12-26 18:25:50 +08:00
return vect;
2022-02-22 01:45:28 +08:00
}
2020-06-26 21:39:53 +08:00
2023-12-26 18:25:50 +08:00
template <typename T>
py::list vector_to_python_list(const std::vector<T>& vect) {
py::list obj;
for (unsigned long i = 0; i < vect.size(); ++i)
obj.append(vect[i]);
return obj;
2020-06-26 21:39:53 +08:00
}
2020-06-25 15:59:37 +08:00
2023-12-26 18:25:50 +08:00
template <typename T>
2023-12-30 15:34:28 +08:00
void extend_vector_with_python_list(std::vector<T>& v, const py::sequence& l) {
2023-12-26 18:25:50 +08:00
for (const auto& item : l)
v.push_back(item.cast<T>());
}
template <typename T>
std::string to_py_str(const T& item) {
2023-12-27 02:16:10 +08:00
std::stringstream out;
out << item;
return out.str();
2023-12-26 18:25:50 +08:00
}
// 直接使用 pybind11 重载 _clone在 C++ 中会丢失 python 中的类型
// 参考https://github.com/pybind/pybind11/issues/1049 进行修改
// PYBIND11_OVERLOAD(IndicatorImpPtr, IndicatorImp, _clone, );
#define PY_CLONE(pyclassname, classname) \
public: \
std::shared_ptr<classname> _clone() override { \
auto self = py::cast(this); \
auto cloned = self.attr("_clone")(); \
\
auto keep_python_state_alive = std::make_shared<py::object>(cloned); \
auto ptr = cloned.cast<pyclassname*>(); \
\
return std::shared_ptr<classname>(keep_python_state_alive, ptr); \
}
} // namespace hku
#endif // HIKYUU_PYTHON_BIND_UTILS_H