Fix alignment issues in CELX routines (Closes: #263)

pull/266/head
Hleb Valoshka 2019-04-08 19:18:39 +03:00
parent 10875c4569
commit df23c60e7a
3 changed files with 37 additions and 6 deletions

View File

@ -12,14 +12,15 @@
#include "celx.h"
#include "celx_internal.h"
#include "celx_vector.h"
#include <celutil/align.h>
using namespace Eigen;
int rotation_new(lua_State* l, const Quaterniond& qd)
{
CelxLua celx(l);
auto q = reinterpret_cast<Quaterniond*>(lua_newuserdata(l, sizeof(Quaterniond)));
memcpy(q, &qd, sizeof(Quaterniond));
auto q = reinterpret_cast<Quaterniond*>(lua_newuserdata(l, aligned_sizeof<Quaterniond>()));
*aligned_addr(q) = qd;
celx.setClass(Celx_Rotation);
return 1;
@ -28,8 +29,9 @@ int rotation_new(lua_State* l, const Quaterniond& qd)
Quaterniond* to_rotation(lua_State* l, int index)
{
CelxLua celx(l);
auto q = reinterpret_cast<Quaterniond*>(celx.checkUserData(index, Celx_Rotation));
return static_cast<Quaterniond*>(celx.checkUserData(index, Celx_Rotation));
return aligned_addr(q);
}
static Quaterniond* this_rotation(lua_State* l)

View File

@ -12,15 +12,17 @@
#include "celx.h"
#include "celx_internal.h"
#include "celx_vector.h"
#include <celutil/align.h>
#include <Eigen/Geometry>
using namespace Eigen;
int vector_new(lua_State* l, const Vector3d& v)
{
CelxLua celx(l);
auto v3 = reinterpret_cast<Vector3d*>(lua_newuserdata(l, sizeof(Vector3d)));
*v3 = v;
auto v3 = reinterpret_cast<Vector3d*>(lua_newuserdata(l, aligned_sizeof<Vector3d>()));
*aligned_addr(v3) = v;
celx.setClass(Celx_Vec3);
return 1;
@ -29,8 +31,9 @@ int vector_new(lua_State* l, const Vector3d& v)
Vector3d* to_vector(lua_State* l, int index)
{
CelxLua celx(l);
auto v = reinterpret_cast<Vector3d*>(celx.checkUserData(index, Celx_Vec3));
return static_cast<Vector3d*>(celx.checkUserData(index, Celx_Vec3));
return aligned_addr(v);
}
static Vector3d* this_vector(lua_State* l)

View File

@ -0,0 +1,26 @@
#pragma once
#include <type_traits>
/*! Returns aligned position for type T inside memory region.
* Designed for usage with functions which allocate unalligned
* memory regions.
*/
template<typename T> T* aligned_addr(T* addr)
{
size_t align = std::alignment_of<T>::value;
return (T*) (((size_t(addr) - 1) / align + 1) * align);
};
template<typename T> T* aligned_addr(T* addr, size_t align)
{
return (T*) (((size_t(addr) - 1) / align + 1) * align);
};
/*! Returns size large enough so an object of type T can be placed
* inside allocated unalligned memory region with its address aligned.
*/
template<typename T> size_t aligned_sizeof()
{
return sizeof(T) + std::alignment_of<T>::value - 1;
};