如何用pybind包装包含虚函数的class模板
how to wrap class template consisting virtual function with pybind
一个 class template
由 pure virtual function
组成并被另一个 class 继承。 我没有找到正确的绑定路径。尝试编译时出现以下Error Message。
我已通过以下 link 找到解决方案 , , 3, 4 但不明白该怎么做。我在这里粘贴了我的代码。
文件夹结构
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)
非常感谢任何建议。
得到解决方案。这是关于 pybind
的 trampoline
。
using Base_Abstract_Only<T>::Base_Abstract_Only;
会解决的
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");
}
一个 class template
由 pure virtual function
组成并被另一个 class 继承。 我没有找到正确的绑定路径。尝试编译时出现以下Error Message。
我已通过以下 link 找到解决方案
文件夹结构
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)
非常感谢任何建议。
得到解决方案。这是关于 pybind
的 trampoline
。
using Base_Abstract_Only<T>::Base_Abstract_Only;
会解决的
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");
}