首页 > 解决方案 > 使用 pybind11 在 C++ 之间传递 Python 大整数(>256 位)

问题描述

我正在为基于 C++ 的加密方案开发一个 python 包装器,其中密钥和密文是非常大的数字(最多 2048 位)。

在 C++ 中,我使用英特尔 BigNumber 类来存储和处理如此大的数字。

由于 Python 通过对象本身支持“看似”无限位的整数,因此我无法通过 Python 将此类变量作为参数传递。

  py::class_<BigNumber>(m, "BigNumber")
      .def(py::init<unsigned int>())
      .def(py::init<int>())
      .def(py::init<BigNumber>())
      .def(py::init([](py::list data) {
        size_t length = data.size();
        unsigned int* pData = new unsigned int[length];
        for (int i = 0; i < length; i++) {
          pData[i] = data[i].cast<unsigned int>();
        }
        return std::unique_ptr<BigNumber>(new BigNumber(pData, length));
      }))
      .def(py::init([](py::array_t<unsigned int> data) {
        py::buffer_info buffer_info = data.request();

        unsigned int* pData = static_cast<unsigned int*>(buffer_info.ptr);
        std::vector<ssize_t> shape = buffer_info.shape;
        return std::unique_ptr<BigNumber>(new BigNumber(pData, shape[0]));
      }))

以上部分允许最多 32 位单个变量或分解大整数的列表/数组(每个 32 位)

如果我想从 Python 中获取非常大的整数作为输入来填充BigNumber类,我应该怎么做才能定义一个def_property_readonly()作为 Python 可理解的大整数对象返回的函数?

Edit1:将大整数从 Python 传递到 C++ 在BigNumber(const char* s)构造函数的帮助下,可以通过以下方式完成:

      .def(py::init([](py::object obj){
        std::string s_obj = py::str(obj);
        return std::unique_ptr<BigNumber>(new BigNumber(&s_obj[0]));
      }))

弄清楚如何做反向,可能std::string与?py::objectpy::cast

标签: pythonc++pybind11bignum

解决方案


第一种情况的答案: 使用 BigNumber 将非常大的整数(> 256 位)对象从 Python 传递到 C++

将大整数从 Python 传递到 C++ 在BigNumber(const char* s)构造函数的帮助下,可以通过以下方式完成:

.def(py::init([](py::object obj){
  std::string s_obj = py::str(obj);
  return std::make_unique<BigNumber>(s_obj.c_str());
}))

但是,用大整数对象返回 Python 仍然是 WIP

我尝试使用以下方式返回 python py::int_

.def("val", [](BigNumber const& self){
  std::string s_hex;
  self.num2hex(s_hex);
  return py::int_(s_hex);
})

但是,当您尝试时,这会调用相同的值错误

>>> int("0x12345")

在 Python 中。

ValueError: invalid literal for int() with base 10: '0x12345'


推荐阅读