如何将浮点数传递给期望 int 的 pybind11 函数

Posted

技术标签:

【中文标题】如何将浮点数传递给期望 int 的 pybind11 函数【英文标题】:How to pass float to a pybind11 function expecting an int 【发布时间】:2020-12-11 00:52:07 【问题描述】:

我从 pybind11 文档中复制了示例:

#include <pybind11/pybind11.h>
namespace py = pybind11;
int add(int i, int j) 
    return i + j;

PYBIND11_MODULE(example, m) 
    m.def("add", &add, "A function which adds two numbers");

这样构建:

g++ -fPIC -shared -I/usr/include/python3.7 -o example.so example.cpp

然后:

$ python3
Python 3.7.3 (default, Jul 25 2020, 13:03:44) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from example import *
>>> add(1, 2)
3
>>> add(1.0, 2.0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: add(): incompatible function arguments. The following argument types are supported:
    1. (arg0: int, arg1: int) -> int

Invoked with: 1.0, 2.0
>>>

我意识到我可以重写add 以获取double 参数,然后在add 的主体内截断它们。但是有没有办法告诉 pybind11 可以将浮点数传递给函数(即使它需要 int 参数)并让它自动执行转换?

根据文档,相反(从整数类型转换为double)是隐式自动完成的。

【问题讨论】:

【参考方案1】:

默默地和隐式地截断为int 是一件可怕的事情,pybind11 不会为你做这件事。如果必须允许,您可以为每个参数类型创建一个重载函数,并让 double 变体代表您进行截断(请记住,这可能不仅会丢失小数点后的精度;double 可以表达比任何整数类型都大得多的数字,所以这些数字会发生不好的事情)。

一个粗略的例子是:

#include <pybind11/pybind11.h>
namespace py = pybind11;
int add_int(int i, int j) 
    return i + j;

int add_double_as_int(double i, double j) 
    return add_int((int)i, (int)j);


PYBIND11_MODULE(example, m) 
    m.def("add", &add_int, "A function which adds two integers");
    m.def("add", &add_double_as_int, "A function which adds two floats after truncating to int");

在 C++ 级别,函数有不同的名称(您也许可以通过创造性的转换similar to the examples for doing it with class methods 来避免这种情况,但这几乎不值得麻烦),但在 Python 级别,它们'将显示为具有文档中描述的多个原型的单个 API。

【讨论】:

【参考方案2】:

C++ 是强类型的。只有当它可以安全地完成时,它才会对基本类型进行自动类型转换。由于整数不能代表 double can C++ 无法自动执行转换的每个值。因此,您需要自己明确地进行转换。我不确定这是如何在 python 中完成的。在 C++ 中,最好使用:

#include \<cmath\>

double dbl = 3.5;

int newval = std::round(dbl);

【讨论】:

以上是关于如何将浮点数传递给期望 int 的 pybind11 函数的主要内容,如果未能解决你的问题,请参考以下文章

将行数传递给Oracle中的列[重复]

如何使用 Swift 将 Float 制服传递给 iOS 金属着色器?

PHP PHP准备语句 - 带有未定义的变量数传递给bind_result()

时间函数的使用

如何将子类作为期望基类的函数的参数传递,然后将该对象传递给指向这些抽象类对象的指针向量?

我应该将啥作为参数传递给期望 NSError** 的方法?