PyBind11: boost::multiprecision::cpp_int to Python
PyBind11: boost::multiprecision::cpp_int to Python
我有兴趣使用pybind11来优化一些使用C++的Python计算。转换文档对我来说意义不大,我想知道是否有人知道如何将boost数据类型,特别是cpp_int转换为Python数据类型,这样我就可以返回计算结果。我想做的一个简单的例子是阶乘:
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <boost/multiprecision/cpp_int.hpp>
using boost::multiprecision::cpp_int;
namespace py = pybind11;
py::int_ fact(int i) {
cpp_int prod = 1;
while(i-- >= 1){
prod *= (i+1);
}
return py::cast(prod);
}
PYBIND11_MODULE(fact, m) {
m.def("fact", &fact,R"pbdoc(
Returns the factorial of a number.
)pbdoc");
}
上面的编译,但当我去使用它时,我得到
TypeError: Unregistered type : boost::multiprecision::number<boost::multiprecision::backends::cpp_int_backend<0u, 0u, (boost::multiprecision::cpp_integer_type)1, (boost::multiprecision::cpp_int_check_type)0, std::allocator<unsigned long long> >, (boost::multiprecision::expression_template_option)1>
所以py不起作用::cast我想
我的笔记本电脑运行Windows 10,我使用的是Anaconda Python 3.7
C:Users15734>python
Python 3.7.1 (default, Dec 10 2018, 22:54:23) [MSC v.1915 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
和Stephan T.Lavavej的MinGW C++8.2.0
C:Users15734>g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/x86_64-w64-mingw32/8.2.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../src/configure --enable-languages=c,c++ --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --disable-multilib --prefix=/c/temp/gcc/dest --with-sysroot=/c/temp/gcc/dest --disable-libstdcxx-pch --disable-libstdcxx-verbose --disable-nls --disable-shared --disable-win32-registry --with-tune=haswell --enable-threads=posix --enable-libgomp
Thread model: posix
gcc version 8.2.0 (GCC)
我还在使用Visual Studio 2017的Build Tools for the vcruntime140.dll,它位于">C:\ProgramFiles(x86)\MicrosoftVisualStudio\2017\BuildTools\VC\Redist\MSVC\14.16.27012\onecore\x64\Microsoft.VC141.CRT"中(我将其复制并粘贴到">C:\MinGW\lib中)。我还将">C:\Anaconda3\Lib\distutils\cygwinccompiler.py"中的所有字符串"gcc"更改为"g++"(我没有更改包含gcc的变量名)。
关键词:
"pybind11";"助推";"C++与Python";"boost::multiprecision::cpp_int">
我得到了这个工作:
#include <boost/multiprecision/cpp_int.hpp>
#include <iomanip>
#include <pybind11/pybind11.h>
#include <sstream>
using cpp_int = boost::multiprecision::cpp_int;
namespace py = pybind11;
namespace pybind11
{
namespace detail
{
template <>
struct type_caster<cpp_int> {
/**
* This macro establishes the name 'cpp_int' in
* function signatures and declares a local variable
* 'value' of type cpp_int
*/
PYBIND11_TYPE_CASTER(cpp_int, _("cpp_int"));
/**
* Conversion part 1 (Python->C++): convert a PyObject into a cpp_int
* instance or return false upon failure. The second argument
* indicates whether implicit conversions should be applied.
*/
bool load(handle src, bool)
{
// Convert into base 16 string (PyNumber_ToBase prepend '0x')
PyObject* tmp = PyNumber_ToBase(src.ptr(), 16);
if (!tmp) return false;
std::string s = py::cast<std::string>(tmp);
value = cpp_int{s}; // explicit cast from string to cpp_int,
// don't need a base here because
// `PyNumber_ToBase` already prepended '0x'
Py_DECREF(tmp);
/* Ensure return code was OK (to avoid out-of-range errors etc) */
return !PyErr_Occurred();
}
/**
* Conversion part 2 (C++ -> Python): convert an cpp_int instance into
* a Python object. The second and third arguments are used to
* indicate the return value policy and parent object (for
* ``return_value_policy::reference_internal``) and are generally
* ignored by implicit casters.
*/
static handle cast(const cpp_int& src, return_value_policy, handle)
{
// Convert cpp_int to base 16 string
std::ostringstream oss;
oss << std::hex << src;
return PyLong_FromString(oss.str().c_str(), nullptr, 16);
}
};
} // namespace detail
} // namespace pybind11
py::int_ fact(int i)
{
cpp_int prod = 1;
while (i-- > 1) prod *= i + 1;
return py::cast(prod);
}
PYBIND11_MODULE(python_example, m)
{
m.def("fact", &fact, R"pbdoc(
Returns the factorial of a number.
)pbdoc");
}
可能不是最快的方法,因为它首先将cpp_int
转换为临时的16进制字符串,然后将该字符串转换为Python整数。
我认为boost::multiprecision::backends::cpp_int_backend<0u, 0u,...
是错误的,您刚刚定义了一个0位数的最小/最大数字类型。此外,它似乎只从字符串中解析cpp_int,这对于多精度数字来说是相当合乎逻辑的。
- 为什么选择 g++ 给予者:"error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]"
- static_cast int to reference to int?
- 访问基类型数组成员(Int-to-type习惯用法)
- Int to Base 2 & 8 优化
- ASCII to int to ASCII (ATMEGA 2560)
- 简单的 int 到字符串转换..int to const char* 无效
- visual Int to char c++
- 隐式转换更改符号性 'int " to 'unsigned int"
- 如何修复此错误错误"error C2440: '=' : cannot convert from 'int (*)[]' to 'int *' "?
- int to char C++ help me
- Int to PCSTR for Winsock DEFAULT_PORT
- 将 double 分配给 const int&vs int to const int&
- "cannot Convert vector<int>* to int"是什么意思?
- 如何解决此棉绒警告"Implicit binary conversion from int to unsigned int"
- c++ int to char
- 为什么我会收到"cannot convert from Dequeu<int> to int"错误?
- "error: invalid conversion from 'int*' to 'int' function"
- "Truncation from int to char"不产生任何结果
- Cast int to void* and void* to int for TMemoryStream->WriteBuffer (C++Builder XE7)
- C++ Int to Array without Libs