如何用pybind包装包含虚函数的类模板 [英] how to wrap class template consisting virtual function with pybind

查看:42
本文介绍了如何用pybind包装包含虚函数的类模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个类模板纯虚拟函数组成,并由另一个类继承. 我没有找到绑定它的正确路径 .尝试编译时,出现了错误消息.
我已经通过以下链接找到了解决方案 2 3

A class template consists of pure virtual function and inherited by another class. I am not getting the right path to bind it. Following Error Message has appeared while trying to compile.
I have gone through the following link to find the solution 1, 2, 3, 4 but don't understand what to do. I am pasted my code here.

文件夹结构

proj
  -include/sample_code.h
  -lib/pybind11
  -scripts/cpp_py_cmake.py (also here pybind module stores)
  -src/
    -binding.cpp
  -CMakeLists.txt

sample_code.h

#include <iostream>
using namespace std;

/**
 * class template with virtual function */

template<typename T = int>
class Base_Abstract
{
protected:
    T base_Variable;

public:
    Base_Abstract(T x):base_Variable{x}{
        std::cout<<"Base_Abstract Class Constructor is called and Mem Var: "<<base_Variable<<std::endl;
    }
    virtual void do_something_abstract(T val) = 0;

    virtual ~Base_Abstract() {}
};

template<typename T = int>
class Derived_Abstract : public Base_Abstract<T>
{
    public:
        Derived_Abstract(T a, T b):Base_Abstract<T>{b}, derived_Variable{a}{
            std::cout<<"Derived_Abstract Class Constructor is called and a: "<<a<<" ,derived_var: "<<derived_Variable<<" , val for base: "<<b<<std::endl;
        }
        void show_derived_value(){ 
            cout<<"show_derived_value() of  Derived_Abstract class derived_Variable: "<<derived_Variable<<endl;
        };
        void do_something_abstract(T g) override{
            cout<<"virtual function is called from Derived_Abstract class when g: "<<g<<endl;
        };

        virtual ~Derived_Abstract(){}

    private:
        T derived_Variable;

};

pybind相关代码 binding.cpp

#include <pybind11/pybind11.h>
#include "sample_code.h"
namespace py = pybind11;

/**
 * class template which is abstract class and inherited
 */

template <typename T = int>
void declare_class_template_abstarct(py::module &m, const std::string& typestr1)
{
    class PyVirtualClass : public Base_Abstract <T>{
        public:
            using Base_1 = Base_Abstract<T>;

            /* Trampoline (need one for each virtual function) */
            void do_something_abstract(int val) override {
                PYBIND11_OVERRIDE_PURE(
                    void, /* Return type */
                    Base_1,      /* Parent class */
                    do_something_abstract,          /* Name of function in C++ (must match Python name) */
                    val      /* Argument(s) */
                    );
            }

    };

    py::class_<Base_Abstract <T>, PyVirtualClass /* <--- trampoline*/>(m,"Base_Abstract")
        .def(py::init<T>())
        .def("do_something_abstract", &Base_Abstract <T>::do_something_abstract);

    py::class_<Derived_Abstract<T>, Base_Abstract<T>>(m, "Derived_Abstract")
        .def(py::init<T,T>())
        .def("show_derived_value", &Derived_Abstract <T>::show_derived_value)
        .def("do_something_abstract", &Derived_Abstract <T>::do_something_abstract);
};

PYBIND11_MODULE(somecode, m) 
{
    declare_class_template_abstarct<int>(m, "int");
}

/*
<%
setup_pybind11(cfg)
%>
*/

CMakeLists.txt 文件,用于编译代码

cmake_minimum_required(VERSION 3.10)
project(somecode)

set(LIB_GEN_PATH ${PROJECT_SOURCE_DIR}/scripts CACHE STRING "Where generated library will be placed")

add_subdirectory(lib/pybind11)

include_directories(${PROJECT_SOURCE_DIR}/include)

pybind11_add_module(${PROJECT_NAME} 
                    ${PROJECT_SOURCE_DIR}/src/binding.cpp)

set_target_properties(${PROJECT_NAME}
    PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY ${LIB_GEN_PATH}
)

cpp_py_cmake.py

import somecode

class_temp_abstract_class_obj = somecode.Derived_Abstract(42, 59)

任何建议都是非常可取的.

Any suggestion is highly appreciable.

推荐答案

找到解决方案.这是关于 pybind 蹦床.
使用Base_Abstract_Only< T> :: Base_Abstract_Only; 即可解决.
在此处给出工作要领 .
binding.cpp

Got the solution. It is about the trampoline of pybind.
using Base_Abstract_Only<T>::Base_Abstract_Only; it will be solved.
A working gist is given here.
binding.cpp

#include <pybind11/pybind11.h>

namespace py = pybind11;


template <typename T = int>
void declare_class_template_abstarct(py::module &m, const std::string& typestr1)
{
    // using Base_2 = Base_Abstract<T>;
    class PyVirtualClass : public Base_Abstract<T>{
        public:
            using Base_Abstract<T>::Base_Abstract;
            // using Base_1 = Base_Abstract<T>;

            /* Trampoline (need one for each virtual function) */
            void do_something_abstract(T val) override {
                PYBIND11_OVERRIDE_PURE(
                    void, /* Return type */
                    Base_Abstract<T>,      /* Parent class */
                    do_something_abstract,          /* Name of function in C++ (must match Python name) */
                    val      /* Argument(s) */
                    );
            }

    };

    py::class_<Base_Abstract <T>, PyVirtualClass /* <--- trampoline*/>(m,"Base_Abstract")
        .def(py::init<T>())
        .def("do_something_abstract", &Base_Abstract <T>::do_something_abstract);

    py::class_<Derived_Abstract<T>, Base_Abstract<T>>(m, "Derived_Abstract")
        .def(py::init<T,T>())
        .def("show_derived_value", &Derived_Abstract <T>::show_derived_value)
        .def("do_something_abstract", &Derived_Abstract <T>::do_something_abstract);
};

PYBIND11_MODULE(somecode, m) 
{
    declare_class_template_abstarct<int>(m, "int");
}

这篇关于如何用pybind包装包含虚函数的类模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆