使用 carma(犰狳矩阵和 numpy 数组)用 pybind11 包装 c++ class 时出错

Error by wrapping c++ class with pybind11 using carma (armadillo matrices and numpy arrays)

我有一个尝试使用 carma and pybind11 to go to and from armadillo matrices and numpy arrays based off of this example 的简单示例。没有 printarma() 函数,代码可以工作,即仅使用 pybind11 包装代码编译,我可以 运行 它在 python 中。这里的问题似乎与卡玛有关。这是代码:

#include <ostream>
#include <iostream>
#include <armadillo>
#include <carma/carma.h>
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>

namespace py = pybind11;

using namespace std;

class Base
{
public:
    virtual void test() = 0;
    virtual void printarma() = 0;
};
class Derived: public Base
{

public:
    void printarma(py::array_t<double> & arr) {arma::Mat<double> mat = carma::arr_to_mat<double>(arr);
            std::cout << mat<< std::endl;}
    void test() {cout << "Test";}
};


PYBIND11_MODULE(example,m) {
    py::class_<Base>(m, "Base");

    py::class_<Derived, Base>(m, "Derived")
        .def(py::init<>())
        .def("test", &Derived::test);
        m.def("printarma", &Derived::printarma,py::arg("arr"));
} 

我运行命令:

c++ -O3 -Wall -shared -std=c++14 -fPIC -larmadillo `python3 -m pybind11 --includes` abstrakt_test.cpp -o example`python3-config --extension-suffix`

错误是:

In file included from /home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/pybind11.h:47,
                 from /home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/numpy.h:12,
                 from /usr/local/include/carma/carma/converters.h:24,
                 from /usr/local/include/carma/carma/arraystore.h:1,
                 from /usr/local/include/carma/carma.h:1,
                 from abstrakt_test.cpp:18:
/home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/detail/init.h: In instantiation of ‘Class* pybind11::detail::initimpl::construct_or_initialize(Args&& ...) [with Class = Derived; Args = {}; typename std::enable_if<(! std::is_constructible<_Tp, _Args>::value), int>::type <anonymous> = 0]’:
/home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/detail/init.h:174:66:   required from ‘static void pybind11::detail::initimpl::constructor<Args>::execute(Class&, const Extra& ...) [with Class = pybind11::class_<Derived, Base>; Extra = {}; typename std::enable_if<(! Class::has_alias), int>::type <anonymous> = 0; Args = {}]’
/home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/pybind11.h:1148:9:   required from ‘pybind11::class_<type_, options>& pybind11::class_<type_, options>::def(const pybind11::detail::initimpl::constructor<Args ...>&, const Extra& ...) [with Args = {}; Extra = {}; type_ = Derived; options = {Base}]’
abstrakt_test.cpp:45:26:   required from here
/home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/detail/init.h:63:64: error: invalid new-expression of abstract class type ‘Derived’
 inline Class *construct_or_initialize(Args &&...args) { return new Class{std::forward<Args>(args)...}; }
                                                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
abstrakt_test.cpp:31:7: note:   because the following virtual functions are pure within ‘Derived’:
 class Derived: public Base
       ^~~~~~~
abstrakt_test.cpp:29:18: note:  ‘virtual void Base::printarma()’
     virtual void printarma() = 0;
                  ^~~~~~~~~
In file included from /home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/numpy.h:12,
                 from /usr/local/include/carma/carma/converters.h:24,
                 from /usr/local/include/carma/carma/arraystore.h:1,
                 from /usr/local/include/carma/carma.h:1,
                 from abstrakt_test.cpp:18:
/home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/pybind11.h: In instantiation of ‘void pybind11::cpp_function::initialize(Func&&, Return (*)(Args ...), const Extra& ...) [with Func = pybind11::cpp_function::cpp_function(Return (Class::*)(Arg ...), const Extra& ...) [with Return = void; Class = Derived; Arg = {pybind11::array_t<double, 16>&}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, pybind11::arg}]::<lambda(Derived*, pybind11::array_t<double>&)>; Return = void; Args = {Derived*, pybind11::array_t<double, 16>&}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, pybind11::arg}]’:
/home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/pybind11.h:78:9:   required from ‘pybind11::cpp_function::cpp_function(Return (Class::*)(Arg ...), const Extra& ...) [with Return = void; Class = Derived; Arg = {pybind11::array_t<double, 16>&}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, pybind11::arg}]’
/home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/pybind11.h:819:22:   required from ‘pybind11::module& pybind11::module::def(const char*, Func&&, const Extra& ...) [with Func = void (Derived::*)(pybind11::array_t<double>&); Extra = {pybind11::arg}]’
abstrakt_test.cpp:47:55:   required from here
/home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/pybind11.h:133:50: error: static assertion failed: The number of argument annotations does not match the number of function arguments
         static_assert(expected_num_args<Extra...>(sizeof...(Args), cast_in::has_args, cast_in::has_kwargs),
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/attr.h:13,
                 from /home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/pybind11.h:44,
                 from /home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/numpy.h:12,
                 from /usr/local/include/carma/carma/converters.h:24,
                 from /usr/local/include/carma/carma/arraystore.h:1,
                 from /usr/local/include/carma/carma.h:1,
                 from abstrakt_test.cpp:18:
/home/mikanim/anaconda3/envs/pybind/lib/python3.7/site-packages/pybind11/include/pybind11/cast.h:1958:57: error: ‘std::enable_if_t<std::is_void<_Res>::value, pybind11::detail::void_type> pybind11::detail::argument_loader<Args>::call(Func&&) && [with Return = void; Guard = pybind11::detail::void_type; Func = pybind11::cpp_function::cpp_function(Return (Class::*)(Arg ...), const Extra& ...) [with Return = void; Class = Derived; Arg = {pybind11::array_t<double, 16>&}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, pybind11::arg}]::<lambda(Derived*, pybind11::array_t<double>&)>&; Args = {Derived*, pybind11::array_t<double, 16>&}; std::enable_if_t<std::is_void<_Res>::value, pybind11::detail::void_type> = pybind11::detail::void_type]’, declared using local type ‘pybind11::cpp_function::cpp_function(Return (Class::*)(Arg ...), const Extra& ...) [with Return = void; Class = Derived; Arg = {pybind11::array_t<double, 16>&}; Extra = {pybind11::name, pybind11::scope, pybind11::sibling, pybind11::arg}]::<lambda(Derived*, pybind11::array_t<double>&)>’, is used but never defined [-fpermissive]
     enable_if_t<std::is_void<Return>::value, void_type> call(Func &&f) && {

提前致谢!

编辑:

没有 carma 的代码:

c++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` abstrakt_test.cpp -o example`python3-config --extension-suffix`



#include <ostream>
#include <iostream>
#include <pybind11/pybind11.h>


namespace py = pybind11;
using namespace std;

class Base
{
public:
    virtual void test() = 0;
};
class Derived: public Base
{

public:

    void test() {cout << "Test";}
};

PYBIND11_MODULE(example,m) {
    py::class_<Base>(m, "Base");

    py::class_<Derived, Base>(m, "Derived")
        .def(py::init<>())
        .def("test", &Derived::test);
} 

最后是两件事:Base class 中的虚函数需要添加 py::array_t<double> & arr.def 末尾的分号需要删除连同 .def 之前的 m。此代码在 python:

中编译和工作
class Base
{
public:
    virtual void test() = 0;
    virtual void printarma(py::array_t<double> & arr) = 0;
};
class Derived: public Base
{

public:
    void printarma(py::array_t<double> & arr) {arma::Mat<double> mat = carma::arr_to_mat<double>(arr);
            std::cout << mat<< std::endl;}
    void test()  {cout << "Test";}
};


PYBIND11_MODULE(example,m) {
    py::class_<Base>(m, "Base");

    py::class_<Derived, Base>(m, "Derived")
        .def(py::init<>())
        .def("test", &Derived::test)
        .def("printarma", &Derived::printarma,py::arg("arr"));