简体   繁体   English

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

[英]How to pass float to a pybind11 function expecting an int

I copied the example from the pybind11 documentation:我从 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");
}

Built it like so:像这样构建它:

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

Then:然后:

$ 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
>>>

I realize I could rewrite add to take double arguments and then truncate them inside the body of add .我意识到我可以重写add以采用double arguments ,然后在add的主体内截断它们。 But is there a way to tell pybind11 that it's ok to to pass floats to the function (even though it takes int arguments) and have it perform the conversion automatically?但是有没有办法告诉 pybind11 可以将浮点数传递给 function (即使它需要int参数)并让它自动执行转换?

According to the docs, the opposite (conversion from integer types to double ) is done implicitly and automatically.根据文档,相反(从 integer 类型转换为double )是隐式自动完成的。

Silently and implicitly truncating to int is a terrible thing to allow, and pybind11 won't do it for you.默默地和隐式地截断为int是一件可怕的事情, pybind11不会为你做这件事。 If you must allow it, you can make an overloaded function for each parameter type, and have the double variant do the truncation on your behalf (keep in mind, this might not just lose precision after the decimal; double can express numbers much larger than any integer type, so bad things'll happen for such numbers).如果您必须允许,您可以为每个参数类型创建一个重载的 function,并让double变体代表您进行截断(请记住,这可能不仅会丢失小数点后的精度; double可以表示比任何 integer 类型,所以这些数字会发生坏事)。

A rough example for doing this would be:一个粗略的例子是:

#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");
}

At the C++ level, the functions have different names (you might be able to avoid this with creative casting similar to the examples for doing it with class methods , but it's hardly worth the trouble), but at the Python level, they'll appear as a single API with multiple prototypes described in the documentation.在 C++ 级别,函数具有不同的名称(您可以通过类似于使用 class 方法的示例进行创造性转换来避免这种情况,但它几乎不值得麻烦),但在 ZA7F5F35426B9274111FC923 级别,它们出现,作为具有文档中描述的多个原型的单个 API。

C++ is strongly typed. C++ 是强类型的。 It will do automatic type conversion of basic types only when it can be done safely.只有当它可以安全地完成时,它才会对基本类型进行自动类型转换。 Since an integer can't represent every value that a double can C++ can't automatically perform the conversion.由于 integer 不能代表双精度罐 C++ 无法自动执行转换的每个值。 So you'll need to explicitly do the conversion yourself.因此,您需要自己明确地进行转换。 I'm not sure how this is done in python.我不确定这是如何在 python 中完成的。 In C++ it is best done with:在 C++ 中,最好使用:

#include \<cmath\>

double dbl = 3.5;

int newval = std::round(dbl);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM