用 operator* 重载包装矩阵乘法
Wrap matrix multiplication with operator* overload
我一直在尝试包装要在 python 中调用的矩阵 c++ class。我希望能够使用丰富的乘法运算符(即 m1 * m2)调用矩阵乘法,但到目前为止,我只设法绑定了一个函数 m3 = multiply(m1, m2)
,我从 python 中得到了它具有派生的相同功能 class:
class mat4(mylib.mat4):
def __init__(self):
super().__init__(self)
def __mul__(self, other):
return multiply(self, other)
但我更喜欢仅从 C++ 进行更清晰的传递,如果有人有任何建议,谢谢。
所以,我试图包装一个不存在的 glm::mat4::operator*(...)
。这是原型:
GLM_FUNC_DECL mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m, T const& s);
需要两个 mat4
参数和 returns 一个 mat4
.
所以解决方案看起来像这样:
struct custom_deleter {
glm::mat4 operator()(glm::mat4* m) {
return *m;
}
};
glm::mat4* mul_mat4(glm::mat4 const &mat1, glm::mat4 const &mat2) {
glm::mat4* tmp = new glm::mat4();
*tmp = glm::operator*(mat1, mat2);
// create unique_ptr to manage memory to ensure memory
// is properly cleaned up
std::unique_ptr<glm::mat4, custom_deleter> _m( tmp );
return _m.get();
}
然后可以在 BOOST_PYTHON_MODULE()
中绑定:
python::class_<glm::mat4, boost::shared_ptr<glm::mat4>, boost::noncopyable>("mat4", python::no_init)
.def("__init__", python::make_constructor(&make_mat4))
.def("__mul__", &mul_mat4, python::return_value_policy<python::manage_new_object>())
;
这是一个完整的例子:
#include <boost/python.hpp>
#include <boost/make_shared.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtx/string_cast.hpp>
struct vec3Wrap : glm::vec3, boost::python::wrapper<glm::vec3>
{
vec3Wrap(float x, float y, float z): glm::vec3(x, y, z) {}
vec3Wrap(float a): glm::vec3(a, a, a) {}
vec3Wrap(): glm::vec3(){}
};
struct custom_deleter_vec {
glm::vec3 operator()(glm::vec3* f){
return *f;
}
};
glm::vec3* mul_vec3(glm::vec3 const &v1, float const &f) {
glm::vec3* tmp = new glm::vec3();
*tmp = glm::operator*(v1, f);
std::unique_ptr<glm::vec3, custom_deleter_vec> _v( tmp );
return _v.get();
}
glm::vec3* add_vec3(glm::vec3 const &v1, glm::vec3 const &v2) {
glm::vec3* tmp = new glm::vec3();
*tmp = glm::operator+(v1, v2);
std::unique_ptr<glm::vec3, custom_deleter_vec> _v( tmp );
return _v.get();
}
boost::shared_ptr<glm::vec3> make_vec3(float x, float y, float z)
{
return boost::make_shared<glm::vec3>(x, y, z);
}
struct custom_deleter {
glm::mat4 operator()(glm::mat4* m) {
return *m;
}
};
glm::mat4* mul_mat4(glm::mat4 const &mat1, glm::mat4 const &mat2) {
glm::mat4* tmp = new glm::mat4();
*tmp = glm::operator*(mat1, mat2);
std::unique_ptr<glm::mat4, custom_deleter> _m( tmp );
return _m.get();
}
std::string print_mat4(glm::mat4 const &m) {
return glm::to_string(m);
}
boost::shared_ptr<glm::mat4> make_mat4(float m)
{
return boost::make_shared<glm::mat4>(m);
}
glm::mat4* _lookAt (glm::vec3 const &eye, glm::vec3 const ¢er, glm::vec3 const &up)
{
glm::mat4 *tmp = new glm::mat4();
*tmp = glm::lookAt(eye, center, up);
std::unique_ptr<glm::mat4, custom_deleter> m( tmp );
return m.get();
}
glm::mat4* _perspective(float const &fovy, float const &aspect, float const &near, float const &far)
{
glm::mat4 *tmp = new glm::mat4();
*tmp = glm::perspective(fovy, aspect, near, far);
std::unique_ptr<glm::mat4, custom_deleter> m( tmp );
return m.get();
}
int main() {
return 0;
}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<glm::mat4, boost::shared_ptr<glm::mat4>, boost::noncopyable>("mat4", python::no_init)
.def("__init__", python::make_constructor(&make_mat4))
.def("__mul__", &mul_mat4, python::return_value_policy<python::manage_new_object>())
.def("__str__", &print_mat4);
python::def("perspective", _perspective, python::return_value_policy<python::manage_new_object>());
python::def("lookAt", _lookAt, python::return_value_policy<python::manage_new_object>());
python::class_<glm::vec3, boost::shared_ptr<glm::vec3>, boost::noncopyable>("vec3", python::no_init)
.def("__init__", python::make_constructor(&make_vec3));
// .def("__mul__", &mul_vec3, python::return_value_policy<python::manage_new_object>())
// .def("__imul__", &mul_vec3, python::return_value_policy<python::manage_new_object>())
// .def("__add__", &add_vec3, python::return_value_policy<python::manage_new_object>())
// .def("__str__", &print_vec3)
// .def_readwrite("x", &vec3::x)
// .def_readwrite("y", &vec3::y)
// .def_readwrite("z", &vec3::z);
}
这可以在 Python 方面允许一些非常整洁的东西:
from example import mat4, perspective, lookAt, vec3
model = mat4(1.0)
view = lookAt(vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, -5.0), vec3(0.0, 1.0, 0.0))
projection = perspective(view, 800, 600, 0.1, 1000.0)
MVP = projection * view * model
我一直在尝试包装要在 python 中调用的矩阵 c++ class。我希望能够使用丰富的乘法运算符(即 m1 * m2)调用矩阵乘法,但到目前为止,我只设法绑定了一个函数 m3 = multiply(m1, m2)
,我从 python 中得到了它具有派生的相同功能 class:
class mat4(mylib.mat4):
def __init__(self):
super().__init__(self)
def __mul__(self, other):
return multiply(self, other)
但我更喜欢仅从 C++ 进行更清晰的传递,如果有人有任何建议,谢谢。
所以,我试图包装一个不存在的 glm::mat4::operator*(...)
。这是原型:
GLM_FUNC_DECL mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m, T const& s);
需要两个 mat4
参数和 returns 一个 mat4
.
所以解决方案看起来像这样:
struct custom_deleter {
glm::mat4 operator()(glm::mat4* m) {
return *m;
}
};
glm::mat4* mul_mat4(glm::mat4 const &mat1, glm::mat4 const &mat2) {
glm::mat4* tmp = new glm::mat4();
*tmp = glm::operator*(mat1, mat2);
// create unique_ptr to manage memory to ensure memory
// is properly cleaned up
std::unique_ptr<glm::mat4, custom_deleter> _m( tmp );
return _m.get();
}
然后可以在 BOOST_PYTHON_MODULE()
中绑定:
python::class_<glm::mat4, boost::shared_ptr<glm::mat4>, boost::noncopyable>("mat4", python::no_init)
.def("__init__", python::make_constructor(&make_mat4))
.def("__mul__", &mul_mat4, python::return_value_policy<python::manage_new_object>())
;
这是一个完整的例子:
#include <boost/python.hpp>
#include <boost/make_shared.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtx/string_cast.hpp>
struct vec3Wrap : glm::vec3, boost::python::wrapper<glm::vec3>
{
vec3Wrap(float x, float y, float z): glm::vec3(x, y, z) {}
vec3Wrap(float a): glm::vec3(a, a, a) {}
vec3Wrap(): glm::vec3(){}
};
struct custom_deleter_vec {
glm::vec3 operator()(glm::vec3* f){
return *f;
}
};
glm::vec3* mul_vec3(glm::vec3 const &v1, float const &f) {
glm::vec3* tmp = new glm::vec3();
*tmp = glm::operator*(v1, f);
std::unique_ptr<glm::vec3, custom_deleter_vec> _v( tmp );
return _v.get();
}
glm::vec3* add_vec3(glm::vec3 const &v1, glm::vec3 const &v2) {
glm::vec3* tmp = new glm::vec3();
*tmp = glm::operator+(v1, v2);
std::unique_ptr<glm::vec3, custom_deleter_vec> _v( tmp );
return _v.get();
}
boost::shared_ptr<glm::vec3> make_vec3(float x, float y, float z)
{
return boost::make_shared<glm::vec3>(x, y, z);
}
struct custom_deleter {
glm::mat4 operator()(glm::mat4* m) {
return *m;
}
};
glm::mat4* mul_mat4(glm::mat4 const &mat1, glm::mat4 const &mat2) {
glm::mat4* tmp = new glm::mat4();
*tmp = glm::operator*(mat1, mat2);
std::unique_ptr<glm::mat4, custom_deleter> _m( tmp );
return _m.get();
}
std::string print_mat4(glm::mat4 const &m) {
return glm::to_string(m);
}
boost::shared_ptr<glm::mat4> make_mat4(float m)
{
return boost::make_shared<glm::mat4>(m);
}
glm::mat4* _lookAt (glm::vec3 const &eye, glm::vec3 const ¢er, glm::vec3 const &up)
{
glm::mat4 *tmp = new glm::mat4();
*tmp = glm::lookAt(eye, center, up);
std::unique_ptr<glm::mat4, custom_deleter> m( tmp );
return m.get();
}
glm::mat4* _perspective(float const &fovy, float const &aspect, float const &near, float const &far)
{
glm::mat4 *tmp = new glm::mat4();
*tmp = glm::perspective(fovy, aspect, near, far);
std::unique_ptr<glm::mat4, custom_deleter> m( tmp );
return m.get();
}
int main() {
return 0;
}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<glm::mat4, boost::shared_ptr<glm::mat4>, boost::noncopyable>("mat4", python::no_init)
.def("__init__", python::make_constructor(&make_mat4))
.def("__mul__", &mul_mat4, python::return_value_policy<python::manage_new_object>())
.def("__str__", &print_mat4);
python::def("perspective", _perspective, python::return_value_policy<python::manage_new_object>());
python::def("lookAt", _lookAt, python::return_value_policy<python::manage_new_object>());
python::class_<glm::vec3, boost::shared_ptr<glm::vec3>, boost::noncopyable>("vec3", python::no_init)
.def("__init__", python::make_constructor(&make_vec3));
// .def("__mul__", &mul_vec3, python::return_value_policy<python::manage_new_object>())
// .def("__imul__", &mul_vec3, python::return_value_policy<python::manage_new_object>())
// .def("__add__", &add_vec3, python::return_value_policy<python::manage_new_object>())
// .def("__str__", &print_vec3)
// .def_readwrite("x", &vec3::x)
// .def_readwrite("y", &vec3::y)
// .def_readwrite("z", &vec3::z);
}
这可以在 Python 方面允许一些非常整洁的东西:
from example import mat4, perspective, lookAt, vec3
model = mat4(1.0)
view = lookAt(vec3(0.0, 0.0, 0.0), vec3(0.0, 0.0, -5.0), vec3(0.0, 1.0, 0.0))
projection = perspective(view, 800, 600, 0.1, 1000.0)
MVP = projection * view * model