错误:没有匹配函数调用‘pybind11::buffer_info::buffer_info

Posted

技术标签:

【中文标题】错误:没有匹配函数调用‘pybind11::buffer_info::buffer_info【英文标题】:error: no matching function for call to ‘pybind11::buffer_info::buffer_info 【发布时间】:2019-01-05 19:34:51 【问题描述】:

我正在尝试使用 pybind11cppimport 包装使用 Armadillo 库的 c++ 函数。但是当我尝试做一些简单的事情时,比如矩阵乘法,我得到了以下错误。

error: no matching function for call to ‘pybind11::buffer_info::buffer_info(double*, long unsigned int, std::__cxx11::string, int, <brace-enclosed initializer list>, <brace-enclosed initializer list>)’
      );
      ^
    In file included from /home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/pytypes.h:13:0,
                     from /home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/cast.h:13,
                     from /home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/attr.h:13,
                     from /home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/pybind11.h:43,
                     from /home/muah/Music/cpp2py/.rendered.code.cpp:3:
    /home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/buffer_info.h:83:5: note: candidate: pybind11::buffer_info::buffer_info(pybind11::buffer_info::private_ctr_tag, void*, pybind11::ssize_t, const string&, pybind11::ssize_t, pybind11::detail::any_container<long int>&&, pybind11::detail::any_container<long int>&&)
         buffer_info(private_ctr_tag, void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim,
         ^~~~~~~~~~~
    /home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/buffer_info.h:83:5: note:   candidate expects 7 arguments, 6 provided
    /home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/buffer_info.h:59:5: note: candidate: pybind11::buffer_info::buffer_info(pybind11::buffer_info&&)
         buffer_info(buffer_info &&other) 

这是犰狳垫到 numpy 之间的转换代码,反之亦然。

#pragma once
#include <armadillo>
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>

namespace py=pybind11;

typedef py::array_t<double, py::array::f_style | py::array::forcecast> pyarr_d;

inline
arma::mat py_to_mat(pyarr_d& pmat)

    py::buffer_info info = pmat.request();
    arma::mat amat;
    if(info.ndim == 1) 
        amat = arma::mat(reinterpret_cast<double*>(info.ptr),info.shape[0],1);
     else 
        amat = arma::mat(reinterpret_cast<double*>(info.ptr),info.shape[0],info.shape[1]);
    
    return amat;



inline
py::array_t<double> mat_to_py(arma::mat &mat)

    py::buffer_info buffer(
        mat.memptr(),
        sizeof(double),
        py::format_descriptor<double>::format(),
        2,
         mat.n_rows, mat.n_cols ,
         sizeof(double), sizeof(double) * mat.n_rows 
    );
    return py::array_t<double>(buffer);

这是c++函数:

<%
cfg['compiler_args'] = ['-std=c++11', '-larmadillo']
setup_pybind11(cfg)
%>

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <armadillo>
#include "py2arma.hpp"  

namespace py = pybind11;


py::array matrix_mul(pyarr_d a, pyarr_d b) 

    arma::mat A = py_to_mat(a);
    arma::mat B = py_to_mat(b);
    arma::mat C = A * B;
    return mat_to_py(C);



PYBIND11_PLUGIN(code) 

    py::module m("code", "lala");
    m.def("matrix_mul",(py::array(*)(pyarr_d,pyarr_d))&matrix_mul);
    return m.ptr();

这是python函数:

import cppimport
import numpy as np

code = cppimport.imp("code")

if __name__ == '__main__':
    xs = np.random.rand(3,3)
    ys = np.random.rand(3,1)

    py_mul = np.dot(xs, ys)
    cpp_mul = code.matrix_mul(xs, ys)
    print(py_mul)
    print(cpp_mul)

此链接包含完整的堆栈跟踪:https://pastebin.com/XuKyQDMQ

我不明白这个错误是什么意思。如何解决这个问题,我是否正确地进行了转换?

编辑:要解决问题,请在矩阵形状之前添加 py::detail::any_container 并跨步缓冲区信息的一部分。并将mat_to_py函数的类型从py::array改为pyarr_d

这解决了代码的所有问题。

【问题讨论】:

嗯...在该错误中跳出的主要内容是std::__cxx11::string 位。我不确定为什么py::format_descriptor&lt;double&gt;::format() 被解释为... 编辑:哦,因为它是一个字符串... 这是无法推断的 ctor:github.com/pybind/pybind11/blob/085a294/include/pybind11/… 调用站点看起来正确,但仍不确定为什么它不起作用... 【参考方案1】:

从上述 cmets 的跟踪来看,似乎是由于您的回溯(第 59 行)中的这个 sn-p:

/home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/buffer_info.h:28:5: note: candidate: pybind11::buffer_info::buffer_info(void*, pybind11::ssize_t, const string&, pybind11::ssize_t, pybind11::detail::any_container<long int>, pybind11::detail::any_container<long int>) buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim, ^~~~~~~~~~~ /home/muah/anaconda3/envs/ising/include/python3.6m/pybind11/buffer_info.h:28:5: note: no known conversion for argument 6 from ‘<brace-enclosed initializer list>’ to ‘pybind11::detail::any_container<long int>’

我的建议是通过首先为这些参数显式构造 py::any_container&lt;size_t&gt;(...) 来完成这项工作,这将帮助您缩小推理出错的范围。也许是因为犰狳的尺寸与来自pybind11ssize_t 不匹配?

【讨论】:

你能给我举个例子吗? 是的!不要写 mat.n_rows, mat.n_cols sizeof... (依赖于从初始化列表到类型的隐式转换),而是明确表示类型:py::detail::any_container&lt;size_t&gt;(mat.n_rows, mat.n_cols) 您的建议修复了它,但我想了解为什么它首先出错了?你为什么这么认为? 在涉及推理时,初始化器列表可能非常挑剔。当编译确定如何将‘&lt;brace-enclosed initializer list&gt;’ 转换为pybind11::detail::any_container&lt;long int&gt;’ 时,C++ 标准不支持此转换,或者您的编译器存在错误(非常类似于 MSVC 有意思,谢谢解释。 C++ 很难导航。我正在使用GCC 6.3.0。它被认为是旧的吗?

以上是关于错误:没有匹配函数调用‘pybind11::buffer_info::buffer_info的主要内容,如果未能解决你的问题,请参考以下文章

错误:没有匹配的调用函数

如何使用 pybind11 在 C++ 线程中调用 Python 函数作为回调

pybind11 以某种方式减慢了 c++ 函数

C++ [错误] 没有匹配的调用函数

没有匹配的函数调用奇怪的错误

创建函数变体向量时出现“调用没有匹配函数”错误