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>
|
2024-04-02 17:00:36 +08:00
|
|
|
|
|
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"
|
2024-03-26 15:43:30 +08:00
|
|
|
|
#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
|