【问题标题】:Passing Python large integers (>256bits) to and from C++ with pybind11使用 pybind11 在 C++ 之间传递 Python 大整数(>256 位)
【发布时间】:2025-12-01 14:20:05
【问题描述】:

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

在 C++ 中,我使用 Intel BigNumber class 来存储和处理如此大的数字。

由于 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 类,我应该如何定义一个返回为 Python 可理解的大整数对象的 def_property_readonly() 函数?

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::stringpy::objectpy::cast

【问题讨论】:

  • 我是个黑客。当我需要在程序和语言之间移动数据时,我会将大数字转换为字符串。
  • C/C++ -- 没有这样的语言。它是 C 或 C++。
  • 请注意,十进制和二进制之间的转换实际上具有非常糟糕的渐近运行时间,因此如果您要通过字符串表示,至少尝试使用十六进制或二进制或其他东西而不是十进制。
  • 你是我喜欢的黑客。使用字符串很简单,而且该死的几乎是万无一失的。这是一个很好的起点(如果没有性能问题,请留下来)。小建议:把return std::unique_ptr&lt;BigNumber&gt;(new BigNumber(&amp;s_obj[0]));换成return std::make_unique(s_obj.c_str());There's less room for error.
  • 如果您在 C 级别更改为使用 GMP 表示数字(很确定有 C++ 包装器),可能有一种直接的方法来创建 gmpy2.xmpz (可变的)或 @ 987654336@(不可变,这意味着您肯定必须复制 - 但是,无论如何您可能都必须复制)。即使您不这样做,您也可以检查 it 如何进行intmpz 转换...

标签: python c++ pybind11 bignum


【解决方案1】:

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

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

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

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

我尝试使用py::int_ 回到python:

.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'

【讨论】:

    最近更新 更多