cppbind: Opimize convert fixed size arrays and more type_traits
This commit is contained in:
parent
7df4f32de6
commit
e81597a176
@ -28,14 +28,13 @@
|
||||
#include <simgear/nasal/cppbind/NasalMe.hxx>
|
||||
#include <simgear/nasal/cppbind/NasalMethodHolder.hxx>
|
||||
#include <simgear/nasal/cppbind/NasalObjectHolder.hxx>
|
||||
#include <simgear/std/type_traits.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -143,9 +142,7 @@ namespace nasal
|
||||
* Convert a Nasal number to a C++ numeric type
|
||||
*/
|
||||
template<class T>
|
||||
typename boost::enable_if< boost::is_arithmetic<T>,
|
||||
T
|
||||
>::type
|
||||
std::enable_if_t<std::is_arithmetic<T>::value, T>
|
||||
from_nasal_helper(naContext c, naRef ref, const T*)
|
||||
{
|
||||
naRef num = naNumValue(ref);
|
||||
@ -174,17 +171,39 @@ namespace nasal
|
||||
return vec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a Nasal vector to a std::array
|
||||
*/
|
||||
template<class T, std::size_t N>
|
||||
std::array<T, N>
|
||||
from_nasal_helper(naContext c, naRef ref, const std::array<T, N>*)
|
||||
{
|
||||
if( !naIsVector(ref) )
|
||||
throw bad_nasal_cast("Not a vector");
|
||||
|
||||
if( naVec_size(ref) != N )
|
||||
throw bad_nasal_cast(
|
||||
"Expected vector with " + std::to_string(N) + " elements"
|
||||
);
|
||||
|
||||
std::array<T, N> arr;
|
||||
|
||||
for(std::size_t i = 0; i < N; ++i)
|
||||
arr[i] = from_nasal_helper(c, naVec_get(ref, i), static_cast<T*>(0));
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a Nasal vector of 2 elements to a 2d vector
|
||||
*/
|
||||
template<class Vec2>
|
||||
typename boost::enable_if<is_vec2<Vec2>, Vec2>::type
|
||||
std::enable_if_t<is_vec2<Vec2>::value, Vec2>
|
||||
from_nasal_helper(naContext c, naRef ref, const Vec2*)
|
||||
{
|
||||
std::vector<double> vec =
|
||||
from_nasal_helper(c, ref, static_cast<std::vector<double>*>(0));
|
||||
if( vec.size() != 2 )
|
||||
throw bad_nasal_cast("Expected vector with two elements");
|
||||
auto vec =
|
||||
from_nasal_helper(c, ref, static_cast<std::array<double, 2>*>(0));
|
||||
|
||||
return Vec2(vec[0], vec[1]);
|
||||
}
|
||||
|
||||
@ -194,10 +213,8 @@ namespace nasal
|
||||
template<class T>
|
||||
SGRect<T> from_nasal_helper(naContext c, naRef ref, const SGRect<T>*)
|
||||
{
|
||||
std::vector<double> vec =
|
||||
from_nasal_helper(c, ref, static_cast<std::vector<double>*>(0));
|
||||
if( vec.size() != 4 )
|
||||
throw bad_nasal_cast("Expected vector with four elements");
|
||||
auto vec =
|
||||
from_nasal_helper(c, ref, static_cast<std::array<double, 4>*>(0));
|
||||
|
||||
return SGRect<T>(vec[0], vec[1], vec[2], vec[3]);
|
||||
}
|
||||
|
@ -25,12 +25,13 @@
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/math/SGRect.hxx>
|
||||
#include <simgear/nasal/cppbind/cppbind_fwd.hxx>
|
||||
#include <simgear/std/type_traits.hxx>
|
||||
|
||||
#include <boost/function/function_fwd.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/call_traits.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <initializer_list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -75,11 +76,66 @@ namespace nasal
|
||||
|
||||
naRef to_nasal_helper(naContext c, const free_function_t& func);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<class T>
|
||||
naRef array_to_nasal(naContext c, const T* arr, size_t size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a fixed size array to a Nasal vector
|
||||
*/
|
||||
template<class T, size_t N>
|
||||
naRef to_nasal_helper(naContext c, const T(&array)[N])
|
||||
{
|
||||
return detail::array_to_nasal(c, array, N);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a fixed size C++ array to a Nasal vector
|
||||
*/
|
||||
template<class T, size_t N>
|
||||
naRef to_nasal_helper(naContext c, const std::array<T, N>& array)
|
||||
{
|
||||
return detail::array_to_nasal(c, array.data(), N);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a std::initializer_list to a Nasal vector
|
||||
*/
|
||||
template<class T>
|
||||
naRef to_nasal_helper(naContext c, std::initializer_list<T> list)
|
||||
{
|
||||
return detail::array_to_nasal(c, list.begin(), list.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert std::vector to a Nasal vector
|
||||
*/
|
||||
template< template<class T, class Alloc> class Vector,
|
||||
class T,
|
||||
class Alloc
|
||||
>
|
||||
std::enable_if_t<
|
||||
std::is_same<Vector<T,Alloc>, std::vector<T,Alloc>>::value,
|
||||
naRef
|
||||
>
|
||||
to_nasal_helper(naContext c, const Vector<T, Alloc>& vec)
|
||||
{
|
||||
return detail::array_to_nasal(c, vec.data(), vec.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a std::map to a Nasal Hash
|
||||
*/
|
||||
template<class Value>
|
||||
naRef to_nasal_helper(naContext c, const std::map<std::string, Value>& map);
|
||||
|
||||
/**
|
||||
* Convert an enum value to the according numeric value
|
||||
*/
|
||||
template<class T>
|
||||
typename boost::enable_if< boost::is_enum<T>, naRef >::type
|
||||
std::enable_if_t<std::is_enum<T>::value, naRef>
|
||||
to_nasal_helper(naContext c, T val)
|
||||
{
|
||||
return naNum(val);
|
||||
@ -89,7 +145,7 @@ namespace nasal
|
||||
* Convert a numeric type to Nasal number
|
||||
*/
|
||||
template<class T>
|
||||
typename boost::enable_if< boost::is_arithmetic<T>, naRef >::type
|
||||
std::enable_if_t<std::is_arithmetic<T>::value, naRef>
|
||||
to_nasal_helper(naContext c, T num)
|
||||
{
|
||||
return naNum(num);
|
||||
@ -99,67 +155,40 @@ namespace nasal
|
||||
* Convert a 2d vector to Nasal vector with 2 elements
|
||||
*/
|
||||
template<class Vec2>
|
||||
typename boost::enable_if<is_vec2<Vec2>, naRef>::type
|
||||
to_nasal_helper(naContext c, const Vec2& vec);
|
||||
|
||||
/**
|
||||
* Convert a std::map to a Nasal Hash
|
||||
*/
|
||||
template<class Value>
|
||||
naRef to_nasal_helper(naContext c, const std::map<std::string, Value>& map);
|
||||
|
||||
/**
|
||||
* Convert a fixed size array to a Nasal vector
|
||||
*/
|
||||
template<class T, size_t N>
|
||||
naRef to_nasal_helper(naContext c, const T(&array)[N]);
|
||||
|
||||
/**
|
||||
* Convert std::vector to Nasal vector
|
||||
*/
|
||||
template< template<class T, class Alloc> class Vector,
|
||||
class T,
|
||||
class Alloc
|
||||
>
|
||||
typename boost::enable_if< boost::is_same< Vector<T,Alloc>,
|
||||
std::vector<T,Alloc>
|
||||
>,
|
||||
naRef
|
||||
>::type
|
||||
to_nasal_helper(naContext c, const Vector<T, Alloc>& vec)
|
||||
{
|
||||
naRef ret = naNewVector(c);
|
||||
naVec_setsize(c, ret, static_cast<int>(vec.size()));
|
||||
for(int i = 0; i < static_cast<int>(vec.size()); ++i)
|
||||
naVec_set(ret, i, to_nasal_helper(c, vec[i]));
|
||||
return ret;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<class Vec2>
|
||||
typename boost::enable_if<is_vec2<Vec2>, naRef>::type
|
||||
std::enable_if_t<is_vec2<Vec2>::value, naRef>
|
||||
to_nasal_helper(naContext c, const Vec2& vec)
|
||||
{
|
||||
// We take just double because in Nasal every number is represented as
|
||||
// double
|
||||
double nasal_vec[2] = {
|
||||
return to_nasal_helper(c, {
|
||||
// We take just double because in Nasal every number is represented as
|
||||
// double
|
||||
static_cast<double>(vec[0]),
|
||||
static_cast<double>(vec[1])
|
||||
};
|
||||
return to_nasal_helper(c, nasal_vec);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a SGRect to a Nasal vector with position and size of the rect
|
||||
*/
|
||||
template<class T>
|
||||
naRef to_nasal_helper(naContext c, const SGRect<T>& rect)
|
||||
{
|
||||
return to_nasal_helper(c, {
|
||||
static_cast<double>(rect.x()),
|
||||
static_cast<double>(rect.y()),
|
||||
static_cast<double>(rect.width()),
|
||||
static_cast<double>(rect.height())
|
||||
});
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<class T>
|
||||
naRef to_nasal_helper(naContext c, const SGRect<T>& rect)
|
||||
naRef detail::array_to_nasal(naContext c, const T* arr, size_t size)
|
||||
{
|
||||
std::vector<double> vec(4);
|
||||
vec[0] = rect.x();
|
||||
vec[1] = rect.y();
|
||||
vec[2] = rect.width();
|
||||
vec[3] = rect.height();
|
||||
|
||||
return to_nasal_helper(c, vec);
|
||||
naRef ret = naNewVector(c);
|
||||
naVec_setsize(c, ret, static_cast<int>(size));
|
||||
for(int i = 0; i < static_cast<int>(size); ++i)
|
||||
naVec_set(ret, i, to_nasal_helper(c, arr[i]));
|
||||
return ret;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -182,17 +211,6 @@ namespace nasal
|
||||
return hash;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<class T, size_t N>
|
||||
naRef to_nasal_helper(naContext c, const T(&array)[N])
|
||||
{
|
||||
naRef ret = naNewVector(c);
|
||||
naVec_setsize(c, ret, static_cast<int>(N));
|
||||
for(int i = 0; i < static_cast<int>(N); ++i)
|
||||
naVec_set(ret, i, to_nasal_helper(c, array[i]));
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace nasal
|
||||
|
||||
#endif /* SG_TO_NASAL_HELPER_HXX_ */
|
||||
|
@ -117,6 +117,51 @@ naRef f_derivedGetX(const Derived& d, naContext c)
|
||||
}
|
||||
naRef f_freeFunction(nasal::CallContext c) { return c.requireArg<naRef>(0); }
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<class T, std::size_t N>
|
||||
ostream& operator<<(ostream& strm, const array<T, N>& vec)
|
||||
{
|
||||
for(auto const& v: vec)
|
||||
strm << "'" << v << "',";
|
||||
return strm;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( cppbind_arrays )
|
||||
{
|
||||
TestContext ctx;
|
||||
|
||||
naRef na_vec = ctx.to_nasal({1., 2., 3.42});
|
||||
BOOST_REQUIRE( naIsVector(na_vec) );
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 0)), 1);
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 1)), 2);
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<double>(naVec_get(na_vec, 2)), 3.42);
|
||||
|
||||
na_vec = ctx.to_nasal(std::initializer_list<double>({1., 2., 3.42}));
|
||||
BOOST_REQUIRE( naIsVector(na_vec) );
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 0)), 1);
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 1)), 2);
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<double>(naVec_get(na_vec, 2)), 3.42);
|
||||
|
||||
using arr_d3_t = std::array<double, 3>;
|
||||
arr_d3_t std_arr = {1., 2., 3.42};
|
||||
na_vec = ctx.to_nasal(std_arr);
|
||||
BOOST_REQUIRE( naIsVector(na_vec) );
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 0)), 1);
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 1)), 2);
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<double>(naVec_get(na_vec, 2)), 3.42);
|
||||
|
||||
double d_arr[] = {1., 2., 3.42};
|
||||
na_vec = ctx.to_nasal(d_arr);
|
||||
BOOST_REQUIRE( naIsVector(na_vec) );
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 0)), 1);
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<int>(naVec_get(na_vec, 1)), 2);
|
||||
BOOST_CHECK_EQUAL(ctx.from_nasal<double>(naVec_get(na_vec, 2)), 3.42);
|
||||
|
||||
BOOST_CHECK_EQUAL(std_arr, ctx.from_nasal<arr_d3_t>(na_vec));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( cppbind_misc_testing )
|
||||
{
|
||||
TestContext c;
|
||||
|
Loading…
Reference in New Issue
Block a user