pybind11模板函数myadd无法导入,基础函数add可用问题求助
问题:pybind11模板函数无法导入的原因与解决办法
我基于pybind11的demo尝试使用模板函数,基础函数add能正常导入使用,但模板实例化的myadd无法导入,报错如下:
>>> from example import add >>> add(2,3) 5L >>> from example import myadd Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: cannot import name myadd
即使复制文档示例代码,只要涉及模板、shared_ptr等复杂结构都会出现该问题,我的源代码如下:
#include <pybind11/pybind11.h> #include <iostream> #include <string> int add(int i, int j) { return i + j; } template <class T> //template <typename T> doesn't work as well T myadd(T a, T b) { return a+b; } namespace py = pybind11; PYBIND11_MODULE(example, m) { // optional module docstring m.doc() = "pybind11 example plugin"; // define add function m.def("add", &add, "A function which adds two numbers"); m.def("myadd", &myadd<int>); m.def("myadd", &myadd<float>); }
原因与解决办法
当前写法多次调用
m.def("myadd", ...),会导致后注册的函数覆盖前一个,最终只有最后一个实例(myadd<float>)被绑定,但pybind11无法自动让Python识别这种重载,所以导入时找不到函数名。正确做法是用pybind11的重载机制,两种实现方式:
- 使用
py::overload_cast明确参数类型,帮助Python识别重载:m.def("myadd", py::overload_cast<int, int>(&myadd<int>), "Add two integers"); m.def("myadd", py::overload_cast<float, float>(&myadd<float>), "Add two floats"); - 强制转换函数指针类型,明确签名:
m.def("myadd", (int(*)(int, int))&myadd<int>, "Add two integers"); m.def("myadd", (float(*)(float, float))&myadd<float>, "Add two floats");
- 使用
另外检查编译过程:确保模板实例化没有被编译器优化掉(你已经显式取了函数指针,一般不会有这个问题,但如果编译时有警告需要留意)。
修改后Python端就能正常导入myadd,并根据参数类型自动调用对应版本:
>>> from example import myadd >>> myadd(2, 3) 5 >>> myadd(2.5, 3.5) 6.0
内容的提问来源于stack exchange,提问作者Vladislav
相关产品推荐
相关产品推荐

